Friday, September 16, 2022

When is inheritance useful?

A major disadvantage of inheritance is not being able to follow the program flow by ctrl + clicking function calls due to some functionality being implemented in ancestor classes. Therefore, I prefer composition over inheritance whenever possible. The one case where inheritance shines is reusing workflows. Let's say all your child classes have a run() method that calls f1(), f2() and f2() in order, where f1, f2, f3 functions are implemented in child classes. If we move the run() method to the ancestor class, child classes would just call that run method, saving you from duplicating the f1, f2, f3 calls in each child.

Monday, September 5, 2022

Studying Algorithms and Data Structures Effectively

There are many ways to solve programming problems. The ideal solution is the one running the fastest and consuming the least amount of memory. The field of algorithms and data structures equips you with the tools to find the best solution. A good solution might run  a million times faster than a naive/brute force solution, which might be the difference between a successful and failed project. It has similarities to mathematics because mathematics always tries to find more concise formulae. For example you can find the sum of consecutive integers from 1 to n by summing each number one by one which has a time complexity of O(n). Or you could think a little more about the problem and observe that there are n/2 pairs of the value of n+1, yielding the famous Gauss formula of n/2*(n+1), which has a time complexity of O(1), i.e. the brute force method gets slower and slower as n increases while the formula always runs at constant time! See a similar Codility problem. A good solution is also environmentally friendly since it consumes less energy.

When studying algorithms and data structures, besides course material, I recommend solving the relevant leetcode questions. Start with the easy ones but note that if this is your first attempt at solving "easy" questions, they won't be easy at all, watch this video for a general approach. Don't just focus on the answer, analyze your solution process even after your solution passes all tests so that it really sinks in.

The good news is that once you solve easy questions, medium ones are not that difficult. The website NeetCode organizes problems nicely according to data structure type and difficulty, I personally use the NeetCode 150 group (see my notes). Python is a concise language to solve coding problems, this 26 minute video teaches you enough python for that. After you finish 29 easy questions on NeetCode 150, move to medium questions, and finally solve the hard ones. It will probably take a couple of months to solve all 150 questions. Besides strengthening you algorithms and data structures foundation, you also will have practiced for coding interviews.

If you want to practice more in a specific area, you can use chatGPT to generate additional questions/problems, e.g. "generate a medium level coding question related to trie data structure"

Visualizing algorithms: Visualgo