LeetCode too Difficult? Start Here First.

Luke Ostrander
CodeX
Published in
10 min readFeb 28, 2022
Source Code: https://github.com/lwoluke/CodingBat-Completed

Have you ever tried LeetCode after seeing that it is one of the most well known sites for coding interview preparation, or that it is very beneficial for improving your coding and creative problem solving skills in general? If you have, you likely have noticed the very steep learning curve, and that even the easiest problems on the site were far too difficult unless you had sufficient experience. I personally experienced this myself, back when I didn’t even know how to solve any of the easiest problems on the site without looking at the answers.

As a result of this experience, I thought to myself, where could I possibly go to learn the skills so that I could be able to solve at least the easiest questions on this site?

There were two main types of issues I experienced on many of the sites that I tried. The first was that the problems would start out very easy, and then all of the sudden, the questions jumped significantly in difficulty to where I didn’t even know how to begin to approach them. Secondly, some questions were too difficult, without a proper buildup to them. Why couldn’t any site start out at an easy difficulty and gradually build? I thought this was the case for every single site, until I found CodingBat. What made this site so great for me was that it actually followed a consistent progression in difficulty, with the average question not taking too long to solve. This allowed me to crank through many questions in just an hour or so. Also, the site had everything I needed in order to solve the problems without unnecessary features. While I still needed to look up solutions every now and then, and to a lesser occasion videos, I hardly ever felt that the questions being asked were too difficult for me, and at least knew of possible ways to attack each problem on the site.

In the rest of this blog post, I’ll share with you the key things that I learned on my path to completing all 317 Java questions on CodingBat.

So first of all, you might be asking why I wanted to complete every question on CodingBat, since that’s a ton of questions! Or you may also be wondering, what are the possible things I could learn if I followed the same path? Or even, how I found out about this site in the first place? I’ll aim to explain my reasoning for each of these below.

At the end of last summer, after looking through many sites to improve my coding skills without any luck, one of my friends suggested I check out CodingBat. While I maybe tried it for a day, at this time I didn’t realize how good this site would turn out to be until midway through the fall 2021 semester at Siena College. One day in my software development course, my professor had us use CodingBat, and work in teams to see who could solve the most problems from the String and Array problem sets. While we didn’t use it much more than this one day, this had made me realize how much I enjoyed solving the problems on here, and that I noticed the problems had scaled in difficulty very consistently. Throughout the rest of this semester, I had managed to go through over 100 problems on the site, but it wasn’t until earlier this year that I decided I wanted to finish the remaining ones. I found the process of completing questions on CodingBat to be very rewarding, but I also knew that I would be taking data structures this spring semester, and noticed that many of the questions on there would be very beneficial for learning related to this course. This led me to want to finish the remaining problems, and in the past month, I finished about 100 of the remaining questions!

Specific Things Covered

The questions on CodingBat range to cover many different topics. The general areas include:

  1. Logic
  2. Loops
  3. Arrays and ArrayLists
  4. Maps
  5. Functional
  6. Recursion

There were even AP Computer Science questions, which I really enjoyed as well. These built upon the difficulty of the logic, loop, and array questions that I previously completed. While I was generally comfortable with these three topics, these questions definitely improved my skills in these areas. One of my favorite questions from the AP CS problem set is called mergeTwo, which involved using two arrays in alphabetical order, and returning an array of the first n characters in order without duplicates. While the solution I first came up with had an efficiency of O(N²), the problem specifically said that it could be solved in O(N). In order to do this, I rewrote my code to look like this:

public String[] mergeTwo(String[] a, String[] b, int n) {

String[] firstOrdered = new String[n];

int posA = 0;
int posB = 0;
int resultsIndex = 0;

while (resultsIndex < n) {

if (a[posA].compareTo(b[posB]) < 0) {
firstOrdered[resultsIndex] = a[posA];
posA++;
} else if (a[posA].compareTo(b[posB]) > 0) {
firstOrdered[resultsIndex] = b[posB];
posB++;
} else {
firstOrdered[resultsIndex] = a[posA];
posA++;
posB++;
}
resultsIndex++;
}

return firstOrdered;
}

This means that each time through the while loop, the current indexes of String array a and b would be compared, and that whichever is smaller would be incremented to the next position in the index. When it comes to the else part of the statement, the values at the two indexes are equal. Since the problem states that there cannot be duplicate elements, I chose the element at the current index in the String array a to get chosen, and then incremented both. By doing so, it’s not possible to end up adding the element at the current index position for b to the final array to be returned.

Functional Programming

This was a topic that I have only been briefly exposed to, which was when I ended up discovering what the lambda expression and → operators were while building my first web app. Out of all the topics that were covered from the CodingBat questions, this is the one I happen to use the least, but still very much enjoy using when I get the opportunity. The main benefit is that it makes coding very concise. Below is an example of functional programming versus using a for loop:

public ArrayList<String> functionalNoZ(ArrayList<String> strings) {    strings.removeIf(s -> s.contains("z"));
return strings;
}

public ArrayList<String> iterativeNoZ(ArrayList<String> strings) {

for (int i = 0; i < strings.size(); i++) {
if (strings.get(i).contains("z"))
{
strings.remove(strings.get(i));
i--;
}
}
return strings;
}

As you can see, this shows functional programming is over 3x as concise based on the number of lines needed! And since this is a simple example, imagine the difference when creating more complex functional statements!

Recursion

Of all these topics, this was the most challenging to grasp. I was first exposed to recursion at the very end of my intro to computer science using Python course. I remember watching so many videos to understand what the heck was going on, and fortunately I was not tested on this at the time.

At the start of last week in my data structures course, we have gotten into this topic, but luckily I had gained more experience since taking the intro CS course. For my data structures course, I had already gone through all of the ZyBooks homework assignments within the first couple weeks of the course starting, which had helped to give me a general understanding of each of the topics we’d be covering later on in the course. Along with this, I had just started the first problem set for recursion on CodingBat, so I felt more confident despite still feeling confused by what was going on. During the first lecture, my data structures professor did something very interesting, that other sources I’ve used for learning recursion have never done. We did examples using strings, while every other place I have tried to learn recursion from only used integer examples. What makes this very useful is that I could understand in a different context how to solve a problem using recursion, allowing myself to pick up on other strategies. Since strings have a certain length, this makes it very easy to see their upper limit in size and the recursive pattern to their base case. After having covered a variety of string and integer examples in class, I was able to finish the first half of the recursion problems very quickly. But then the second half of the problems took it up a notch when it came to the difficulty. The first half covered basic recursion, but the second half covered something called recursive backtracking. According to the definition on Wikipedia:

Backtracking can be defined as a general algorithmic technique that considers searching every possible combination in order to solve a computational problem.

Out of all the problems in the second half of recursion, I found the first to be the most challenging since this was my first time being exposed to this type of problem, in which all of the remaining questions on recursion covered. From CodingBat, the question called groupSum is stated below:

Given an array of ints, is it possible to choose a group of some of the ints, such that the group sums to the given target? This is a classic backtracking recursion problem. Once you understand the recursive backtracking strategy in this problem, you can use the same pattern for many problems to search a space of choices. Rather than looking at the whole array, our convention is to consider the part of the array starting at index start and continuing to the end of the array. The caller can specify the whole array simply by passing start as 0. No loops are needed — the recursive calls progress down the array.

The only part of this problem I was able to come up with before looking at the hint and solution was to see if start is greater than or equal to the length of the int array, and to return true or false depending on if the target was equal to 0. In order to understand the problem completely, I needed to analyze multiple sources. After doing so, I was able to understand the flow of how the problem was solved. To do so, there needs to be cases for recursion where the value at the start position is chosen, or that it is not. This means that there will be many combinations that will be looked at in order to determine if the target value exists. Below is a very helpful diagram that I found from this YouTube video explaining how recursive backtracking works for this particular question.

From the Daniel Sutantyo YouTube Channel

This shows each of the possible combinations at various recursive calls for what the target value is currently at. Initially, each of the cases for taking a value are chosen, which results in the target value becoming -4. After this, the other recursive call is checked for not picking the last value. This process continues to check the other combinations of the recursive calls until the target equals 0.

// What I came up with
public boolean groupSum(int start, int[] nums, int target) {
if (start >= nums.length) return (target == 0);

if (groupSum(start + 1, nums, target - nums[start])) return true;

if (groupSum(start + 1, nums, target)) return true;

return false;
}
// Optimized solution
public boolean groupSum(int start, int[] nums, int target) {
if (start >= nums.length) return (target == 0);

return (groupSum(start + 1, nums, target - nums[start]))
|| (groupSum(start + 1, nums, target));
}

TLDR version

While I was very eager to start LeetCode last summer, I found that even the easiest questions on the site were far too difficult for me then. For this reason, I spent a lot of time searching for another site to level up my coding skills. I discovered that CodingBat would be best for me, and am glad that I took the time to complete each of the 317 Java questions. Now having finished this, I’m certainly ready for LeetCode.

Special thanks to Nick Parlante, who is the creator of CodingBat, and lecturer for Computer Science at Stanford. This site has really helped to improve my coding skills, and its amazing to think of how many students his efforts have helped over the years.

Update since original post — 4.10.2022

I decided to go back and complete all 72 of the Python questions after realizing that Python would be the best overall programming language for me when it comes to coding interviews. I have used Python a lot in the past, and really enjoy how concise and readable it is. For this reason it is easier to share my thought process when answering questions in a timed format. This way, I wouldn’t be bogged down thinking about data types, handling exceptions, and things crucial to other programming languages.

Since I completed all the Java questions, completing all the Python questions was very quick, and it definitely helped me get comfortable with the Python syntax again.

Overall, Python will allow me to better utilize my problem solving skills, and I highly recommend CodingBat to everyone.

Works Cited:

Abiy, Thaddeus, et al. “Recursive Backtracking.” Brilliant Math & Science Wiki, Brilliant, https://brilliant.org/wiki/recursive-backtracking/.

“Backtracking.” Wikipedia, Wikimedia Foundation, 16 Feb. 2022, https://en.wikipedia.org/wiki/Backtracking.

Huang, Shen. “What Is Big O Notation Explained: Space and Time Complexity.” FreeCodeCamp.org, FreeCodeCamp.org, 9 June 2021, https://www.freecodecamp.org/news/big-o-notation-why-it-matters-and-why-it-doesnt-1674cfa8a23c/.

Parlante, Nick. “CodingBat.” Codingbat, https://codingbat.com/about.html.

Sutantyo, Daniel. “CP-3.002 — Recursive Backtracking — GroupSum (CodingBat).” YouTube.com, Google, https://www.youtube.com/watch?v=dmAJMyJyxoY&t=911s.

--

--

Luke Ostrander
CodeX
Writer for

Assistant Technical Director - Software Engineering & UX @ DNEG | Enhancing Experiences for Netflix, Apple, and other top clients