My Top Ten Favorite Leetcode Questions
Over the summer, I have been on what is commonly referred to as “the Leetcode Grind,” or a period of time spent learning about and solving problems related to data structures and algorithms. In addition to Leetcode, I have also used Pramp, Interviewing.io, Interview Cake, Geeks for Geeks, AlgoExpert, Cracking The Coding Interview book, YouTube, Udemy, my friends, and Fullstack Academy lectures to supplement my understanding.
After completing 100+ problems (across all previously listed platforms), doing 50+ mock technical interviews, and reviewing the solutions of a handful more, I have rounded up top ten problems from Leetcode that I’ve enjoyed solving or learning the solution about so far. I’m writing this so that I can reflect on what I’ve done so far, understand the patterns better, and maybe hopefully also help anyone who’s looking for a similar content.
***Spoiler Alert: I do gloss over the solutions in this article for some of the problems so tread carefully if you want to solve the problems on your own first.***
In a nutshell, you have to detect if a Linked List has a cycle or not. I wasn’t able to solve this problem on my first try, but once I learned about the two pointer approach — one slower pointer and one fast pointer — my mind was blown.
The best analogy I can use to explain this approach is to think of a racing track. If a race track is circular, and you have two cars going at different speeds, they are bound to meet again at some point. (The faster one is going to catch up to the slower one.) This isn’t the case when you have a race track that’s only straight.
After learning this, linked lists (singly and doubly) became my favorite comfort data structure. There’s something easy-going, flexible, and low-maintenance about them because they don’t require contiguous space in memory, they’re still a linear data structure, AND you can have both previous and next pointers which makes traversing, inserting and deleting a breeze.
Merging Overlapping Intervals. This is a great Array problem with a straight forward logic. Given enough time, I think this is an intuitive problem to solve even if you haven’t seen it before. Still, I think it’s easy to get tripped up on the approach and the implementation when you’re under a time crunch. If you have solved it once or twice beforehand, it makes the next times much more efficient.
I also think this is one of those problems that don’t feel too conceptual because you can relate to their use-cases in our day-to-day lives (our calendars, schedules, etc.)
A similar problem that is also worth checking out is #253 Meeting Rooms II.
Given a number of courses and their pre-requisites, return the ordering of courses one should take to finish all the courses. This is a fun problem that gives you an opportunity to flex your muscles on several data structures like Graphs and Queues. Most importantly, it introduced me to Topological Sort (Kahn’s Algorithm). It took me a while to arrive to this on my own and to recognize similar problems, but if anyone wants to learn from my learnings, it is to consider Topological Sort when you see a DAG. (Directed Acyclic Graph) And remember, trees are also DAGs.
I think Leetcode does a great job explaining this problem’s solution so make sure to check that out. Also take a look at MIT OpenCourseWare’s lecture on this topic (fast forward to 41:56). Once you can efficiently solve this problem and can explain the time and space complexity, I think you’ll have a great start to solve other graph, queue and topological sort problems.
If you are up for a challenge after this one, check out #269 Alien Dictionary.
Return the top K frequent elements in a given array. I think this problem is a great introduction to practice using Heaps a.k.a Priority Queues which are probably my second favorite data structure after Linked Lists. (Something about the formula to determine parent/left/right order in a queue is a chef’s kiss.) I personally found Colt Steele’s walkthrough on this data structure very helpful.
Whenever you’re asked to return K elements, consider using a Heap/Priority Queue. A similar problem to check out is #973 K Closest Points to Origin.
Given a string containing digits from
2-9 inclusive, return all possible letter combinations that the number could represent. I never thought I would ever say I love recursive solutions but here I am. The recursive backtracking solution to this problem has proven useful to solve many other similar problems around Depth-First Search and Backtracking. (Also, the phone pad in this problem brings back good old memories of the time when I had a flip phone.)
Anytime you encounter a prompt that asks you to return all combinations of something, consider using a backtracking approach to get started. I think Kenny Talks Code does an excellent job covering backtracking and DFS in this YouTube video. For more DFS / backtracking problems, he recommended checking out #200 Number of Islands (Another fantastic problem that would make my top ten if it wasn’t an honorable mention here. It helps you practice traversing a matrix), #51 N-Queens, #22 Generate Parentheses and #78 Subsets. You can never go wrong with solving many DFS problems to build muscle memory.
Given two strings, return the number of edits you have to do to turn str1 into str2. This is one of those problems where, if you didn’t learn about Dynamic Programming (specifically Levenshtein distance), it is hard to come up with an optimized solution on your own. When you have a decision making problem like this one (where you have to decide between finite options at each iteration such as making one of three edits or no edit at each character), the brute force approach could be to make a recursive call on all the options and return the best solution between them. Try to then see if there are solutions to subproblems you can store so you don’t repeat the same operations.
Take a look at Geeks for Geeks’ explanation on how to solve it using recursion or the Levenshtein distance algorithm. They even show you how you can optimize the latter to O(m) — my favorite part. It took over three days and at least five different resources explaining the 2D array DP approach (Levenshtein) for me to finally understand. The explanation that made it all click for me is Back To Back SWE’s video on this topic.
Given an array of integers and a target integer, return the total number of continuous subarrays whose sum equals to the target integer. This problem is a good reminder that sometimes you need to look into how you can tradeoff space complexity to improve time complexity. My favorite part about it is that the solution uses Prefix Sum. I think Erricho’s 4 minute explanation on YouTube is the best one out there on how prefix sum works. As he stated, once you recall that prefixSum[L…R] = prefixSum[R]-prefixSum[L-1], you have all you need to solve the prompt.
Given a rotated sorted array of numbers and a target integer, return the index of target if it is in the array or -1 if it is not. Whenever you are dealing with a sorted array, consider Binary Search (an important searching algorithm that has O(log n) time complexity). I think this is a great problem to practice binary search and also to briefly expose yourself to the concept of rotated arrays which I think are pretty neat and could come in handy.
My favorite lecture (and maybe my first ever computer science related lecture) is Lecture 0 from Harvard’s CS50 Introduction to Computer Science course where Professor David Malan ripped up a dictionary to illustrate how Binary Search works. I will never forget it.
Given a binary matrix and a couple of constraints, return the shortest path from the top left corner of the matrix to the bottom right. This is a great problem to practice Breadth-First Search (the first searching algorithm to consider when asked to find a shortest path since it explores all the neighboring nodes first instead of going deep into each node first like DFS), and traversing through a matrix.
I think a challenging next step up from this problem is #787 Cheapest Flight Within K Stops. If you have Leetcode Premium, I recommend checking out their solution explanation on how you can solve this using Dijkstra’s Algorithm.
We can’t conclude the list without a good Binary Search Tree (BST) problem. Given a binary search tree, return the Kth smallest element. When solving problems like this, I find it helpful to pick concrete examples to do a walk through with and paying close attention to how I’m making decisions (when do I go left vs. right) for that example. Start with something simple; how would you return the smallest element in a binary search tree. Then, build from there. Remember that each child node can be the root of subtrees.
Other tree problems to check out are #98 Validate Binary Search Tree, #116 Populating Next Right Pointers in Each Node, and #951 Flip Equivalent Binary Tree. Geeks for Geeks also has a great walkthrough of different tree traversals if you need to brush up on them.
Well, this wraps up my top ten (and then some)! I hope this list could be a useful resource to someone somehow. There are still plenty left to solve and to learn about so I’m sure I’ll come across more interesting problems along the way. If you have a recommendation on any other Data Structure/Algorithm (and even Object-Oriented Design/System Design) question I should check out, feel free to leave it in the comments.