Understanding the 5 Levels of LeetCode to Crack Coding Interview
Most people plateau at early LeetCode levels. This post explains why and uses the "longest palindromic substring problem" to show how to level up.
Join the DZone community and get the full member experience.
Join For FreeThere are five levels of LeetCode, and most people are stuck at levels one and two. Many of you can solve LeetCode problems but still cannot get a job. Why is that?
Whether you like it or not, coding interviews are a competition. There are other people who are interviewing for the exact same position as you. At the end of the day, it's all about what your level is compared to them.
Look, we all want to progress to the next level, but for that, you need to know what your current level is and where you need to go. That's why I am writing this article.
I'll help you understand what your current level is, and how to get to the next level. I'm going to take the example of the longest palindromic substring problem to show these levels.
This problem asks you to find a substring within a given string that is also a palindrome. Let’s break down how developers at different levels tackle this problem.
Level One
At level one, you spend a lot of time trying to understand what the problem is asking. What is a substring? What's a palindrome? It feels like reading a foreign language. By the time you grasp the question, you're still completely stuck on what to do next. You might write a line or two of code, but then you hit a wall. Hours pass, and you're still staring at the same lines, hoping for divine intervention. You keep rereading the problem statement, thinking that you might have missed something obvious. You know that you need to find a part of the string that reads the same forwards and backwards, but where do you even start? If this sounds like you, do not worry. Everyone starts here. The key is not to give up. Push through those first 10 or 15 problems, no matter how frustrating they are. That's your ticket to the next level.
Level Two
Level two is when things start to click, and your confidence picks up. You have wrestled with a few problems, and you're starting to see some patterns. When you look at the longest palindromic substring problem, you think, "This is simple." The solution is right there in the name. You break it down: substring, palindrome, and longest. So you figure that you will find all the substrings, check which ones are palindromes, and keep track of the longest one. Simple, right?
After some struggle, you might come up with a solution like this.
def longestPalindrome(self, s: str) -> str:
def isPalindrome(s):
return s == s[::-1]
for length in range(len(s), 0, -1):
for start in range(len(s) - length + 1):
if isPalindrome(s[start:start+length]):
return s[start:start+length]
return ""
You're feeling pretty good about yourself. You solved the problem. Then you realize that there are two nested for loops, and checking for palindrome is another operation. That's an order n cubed time complexity. Not great, but hey, it works. This is where most people spend their first 50 problems or so. You're solving the problems, but the efficiency is not quite there yet.
At this level, you are also learning about the edge cases. What if the input is an empty string, or a single character, or what if all the characters are the same? These things start becoming the core of your problem-solving process. You might also start noticing patterns. For example, you might realize that checking if a string is a palindrome is a common operation, so you create a separate function for it. This is your first step towards modular thinking, which is a crucial skill in software development.
But you're still approaching each problem as a unique challenge. You have not yet developed the ability to see similarities between different problems, or to apply techniques from one problem to another. But don't worry—that's coming.
Level Three
The next level, level three, is where things start to get interesting. You are not just solving problems. You are anticipating issues before they even show up. When the first brute-force solution pops up in your head, you immediately start considering time and space complexity. You start asking yourself, "Am I doing some unnecessary work here?" Do you really need to look at all the possible substrings?
Think about it for a moment. If a substring is not a palindrome, anything you get by expanding it outwards cannot be a palindrome either. This insight leads you to a new approach: start from the center and expand outwards. With this in mind you might be able to come up with a solution like this.
def longestPalindrome(self, s: str) -> str:
def expandAroundCenter(s, left, right):
while left >= 0 and right < len(s) and s[left] == s[right]:
left -= 1
right += 1
return s[left+1:right]
longest = ""
for i in range(len(s)):
# Check odd length palindromes
palindrome1 = expandAroundCenter(s, i, i)
# Check even length palindromes
palindrome2 = expandAroundCenter(s, i, i+1)
longest = max(longest, palindrome1, palindrome2, key=len)
return longest
This solution has a time complexity of order n squared is a significant improvement over your last solution.
Jumping from level two to level three is very big. You are not just writing code that works—you are writing efficient code. You can identify why an algorithm is inefficient, and you're always on the lookout for repeated work.
This level can last up to about 200 problems. At this level, you're starting to think like an engineer. You are analyzing the problem, considering different approaches, and choosing the most efficient one. You're also developing a sense of algorithmic patterns. You start to recognize that certain types of problems often have similar solutions. For example, you might recognize that problems involving substrings or subarrays often benefit from some kind of sliding window or two-pointer technique.
Your problem-solving process is becoming more structured. Before you start coding, you spend some time thinking about the problem, considering edge cases, and planning your approach. You might even start writing pseudocode to organize your thoughts before diving into the actual implementation.
Moving on to Level Four
Level four is where you actually start feeling like a chess grandmaster. You have solved hundreds of problems by now. You have mastered advanced data structures like graphs and tries. You can quickly recognize problem patterns and algorithms that might work. When you see the longest palindromic substring problem now, your brain quickly jumps to dynamic programming. You start thinking, "Is there a way to store and reuse the information about palindromic substrings?"
You notice that if you want to know whether the substring between index i and index j is a palindrome,
You just need to check if the characters at i and j are the same, and if the substring between i + 1 and j - 1 is a palindrome. This leads you to a DP solution that looks like this:
def longestPalindrome(self, s: str) -> str:
n = len(s)
dp = [[False] * n for _ in range(n)] # Fixed 'false' to 'False'
longest = ""
# All substrings of length 1 are palindromes
for i in range(n):
dp[i][i] = True
longest = s[i]
# Check for substrings of length 2
for i in range(n - 1):
if s[i] == s[i + 1]:
dp[i][i + 1] = True
longest = s[i:i+2] # Fixed 't' to 'i'
# Check for substrings of length 3 and above
for length in range(3, n + 1):
for i in range(n - length + 1):
j = i + length - 1
dp[i][j] = (s[i] == s[j]) and dp[i+1][j-1]
if dp[i][j] and length > len(longest):
longest = s[i:j+1]
return longest
But here's the catch—this DP solution still has the time complexity of order n squared, which is the same as the level three solution.
So What's the Difference?
At level four, you can come up with multiple optimal solutions for a problem. You understand the trade-offs between different approaches. But be careful—your brain might start finding complexity where it does not even exist. You know so many algorithms now that you're itching to apply them, even when a simpler solution might be good enough.
At this level, your problem-solving skills have become highly sophisticated. You're not just applying known algorithms —you're adapting and combining them in creative ways. Your understanding of time and space complexity is now intuitive. You can often predict the complexity of an algorithm just by glancing at it, and you're always looking for ways to optimize further.
Your coding skills have also reached a high level of proficiency. You write clean, modular, and easily understandable code. Another important aspect of level four is your ability to explain your solutions clearly. You can break down complex algorithms into understandable components and articulate your thought process. This is a crucial skill for technical interviews.
People who have solved around 500 problems are usually at this level.
Level Five
Level five is the land of strong competitive programmers. At this level, you're not just solving the problem—you're analyzing its theoretical limits. You are asking, "What is the best possible time complexity for this problem?" You also know many obscure algorithms to solve specific problems.
For the longest palindromic substring problem, you would know about Manacher's algorithm, which solves it in linear time. Your solution might look something like this.
def longestPalindrome(self, s: str) -> str:
# Preprocess the string
T = '#'.join('^{}$'.format(s))
n = len(T)
P = [0] * n
C = R = 0
for i in range(1, n-1):
P[i] = (R > i) and min(R - i, P[2*C - i]) # Fixed 'c' to 'C'
# Attempt to expand palindrome centered at i
while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
P[i] += 1
# If palindrome centered at i expands past R,
# adjust center based on expanded palindrome.
if i + P[i] > R:
C, R = i, i + P[i]
# Find the maximum element in P
maxLen, centerIndex = max((n, i) for i, n in enumerate(P))
return s[(centerIndex - maxLen)//2: (centerIndex + maxLen)//2]
The solution uses the symmetry of palindromes in a way that's frankly mind-bending for most of us. If you're curious about how it works—well, that's a whole article in itself.
At level five, your understanding of data structures and algorithms is quite profound. You can look at a hard problem and often have intuition of the optimal solution, even if it's not obvious how to implement it. You're also well-versed in advanced mathematical concepts and can apply them to algorithmic problems—number theory, probability theory, etc. These are all the tools in your problem-solving arsenal.
Your coding skills are also exceptional. You can implement complex algorithms correctly on your first try, and your code is not just correct, but elegant.
But here's the thing—you don't need to be at level five to get a job at big tech companies. I'm more of a level four myself, and I'm doing just fine. I could not come up with Manacher's algorithm in my wildest dreams, let alone in an interview setting. The point is—don't get intimidated by level fives you encounter in life. Do not give up before you even start.
With the right attitude and consistent practice, anyone can reach level four—and that's more than enough for most software engineering roles.
As you progress through these levels, it's important to maintain the right perspective. Each level builds on the skills of the previous ones but also brings new challenges.
- At level one, the challenge is understanding the problem.
- At level two, it's implementing a working solution.
- At level three, it's optimizing the solution.
- At level four, it's mastering a wide range of algorithmic techniques.
- And at level five, it's pushing the boundaries of what's possible.
That's all for today, and I will see in my next post. Until then, you can read How to Become a Software Engineer Without a CS Degree.
Opinions expressed by DZone contributors are their own.
Comments