The best way to learn JavaScript is to practice, practice, practice. That’s why today we will go over 10 coding challenges to level up your JavaScript skills. These exercises are useful for any JavaScript developer. If you’re an absolute beginner, it will be helpful to check out our beginner’s guide before diving in.
JavaScript challenges can be difficult enough without us trying to make them harder for ourselves. One of the ways to make them easier is to follow principles outlined in a short book by George Polya called How To Solve It. These steps are as follows:
As we challenge ourselves in the next ten problems, keep these steps in mind. Keep in mind that there are several ways to solve these problems. As long as you can explain your thought-process in good detail, your answer is probably fine!
Today we will cover:
Write a function that accepts an array of strings. Return the longest string.
String[]
= an array of stringsString
= the longest of the strings in the arrayDo we need to consider if there are no strings in the array?
Do we need to consider times when all of the strings are the same length?
For this problem, we need to:
// Try it out yourself here before checking the solution!
There are two different ways listed here as a possible solution to this problem: one uses the ES5 Syntax and uses the ES6 Syntax.
In both solutions, we initially need to declare a longest
variable and initialize it to an empty string.
In the ES5 solution, we are utilizing a traditional for loop structure to look at each index in the array. We are using the array method forEach
to iterate over the array in the ES6 solution.
As we iterate through the data structure, we want to take a look at the length of each string. In JavaScript, we can do that with the length property.
In the ES5 solution, we utilized a conditional statement to see if the current (arr[i]
) string’s length is longer than (but not equal to) the current longest string(longest
). The ES6 solution takes another approach with using the Math
object property max
as a shortcut for the conditional logic in the ES5 version.
If the string is longer, we assign it to the longest variable we already created.
Return the longest as our function’s terminal statement in both cases.
Write a function that takes a string, and returns the character that is most commonly used in the string.
String
= one StringString
= the single character that shows up the most in the given stringDo we need to consider if there is no string given?
Do we need to consider times when more than one character shows up the same number of times?
To find the character most often used in a string, we need to be able to count how many of each kind we have. We can do this using an object that has key:value pairs.
maxCharCount
and new max key to maxChar
.maxChar
// Try it out yourself here before checking the solution!
Create a charCount
object. This object can be named whatever you’d like as long as it’s consistent.
Use a standard for loop to iterate through the string, and check to see if it exists in the charCount
object. If it does, add 1 to CharCount[key]
and reassign it to the same variable. The pipes here will cover any instance where the key does not yet exist in the object and initialize the count to 1.
Loop through the object using a for...in
loop. This type of loop allows us to iterate over each property in an object to look at its value. In this instance we want to find the largest number.
The wording for this problem indicates that they want us to find the last max number (in the case there is more than one character with the same amount of appearances), so we use >=
to reassign the maxChar
if needed.
Return our maxChar
.
Create a function that takes in two strings as two parameters and returns a boolean that indicates whether or not the first string is an anagram of the second string.
String
, String
= two StringsBoolean
are either true
or false
. True
if they are anagrams of each other, and false
if they are not.What is an anagram?
Do we need to consider whitespace?
If an anagram is just a bunch of letters jumbled around, we can see if the strings are anagrams of each other by:
Comparing the length: if they are not same length, they are not an anagram of the other
Sorting the string and using an equality operator to see if it’s equal.
There are a couple of different ways to solve this problem.
// Try it out yourself here before checking the solution!
false
.true
. If not, it will return false
.This particular solution considers white space by sorting it to the end of the string, so it doesn’t necessarily matter if it’s counted or not.
Given a string, write a function that will return whether or not that string is a palindrome.
String
= one StringBoolean
means either true
or false
. true
if string is a palindrome; false
if it is not.Do we need to consider whitespace?
Does the palindrome need to be in the dictionary?
// Try it out yourself here before checking the solution!
This one is deceptively simple. You just need to have knowledge of array methods and how to work with strings in conjunction with those methods. Practice how this could possibly be done without the methods so you know how these methods work under the hood.
Learn JavaScript without scrubbing through videos or documentation. Educative’s text-based courses are easy to skim and feature live coding environments, making learning quick and efficient.
The Complete Guide to Modern JavaScript
Given a string possibly containing three types of braces ({}
, []
, ()
), write a function that returns a Boolean indicating whether the given string contains a valid nesting of braces.
String
= one StringBoolean
means either true
or false
. true
if string has balanced brackets; false
if it does not.What do you mean by balanced brackets?
Will the string only have brackets in it?
Because we are looking for nested balanced brackets, we are looking to use a data structure to store the open brackets we have seen so far.
As we come to a closing bracket, we need to look to see if the last bracket added to the data structure matches the opposite of the current bracket.
If your data structure is empty by the time we get to the end of the string, we have balanced brackets.
// Try it out yourself here before checking the solution!
The process for this particular problem is more about checking for failures. We use a data structure called a stack that takes a first in, last out approach to do that.
When we come across an open bracket, we push it on to the stack. When we come across a closed one, we check to see if the last index of the stack is the opposite the current character.
If the stack is empty by the time we get to the end of our logic, we have balanced brackets.
An Armstrong number is an n-digit number that is equal to the sum of the $nth$ powers of its digits. Determine if the input number is an Armstrong number. Return either true or false.
Number
= n-digit numberBoolean
means either true
or false
. true
if number is Armstrong Number; false
if it is not.May I have an example please?
Remember that in JavaScript type coercion exists. When working with Numbers is JS, remember to check the typeof the number. If it is a string, you’ll need to plan for that. This is really important when working with math in JS.
// Try it out yourself before clicking on the solution tab!
To solve this problem, we change the number to a string, figure out the power by getting the length of the number, and then use a for loop to add up the individual numbers ^
length of the number passed in.
We then check to see if the sum is equal to the original number. If it is, it is an Armstrong number.
Given an array of objects, sort the objects by population size. Return the entire object.
array
of objectsarray
of objects, sorted by populationJavaScript has a built-in array method called sort() that we can use for this particular exercise.
What’s interesting about this particular method is that in JavaScript, if you don’t use a callback compare function to sort the array of objects, the default sort method is used to sort by characters rather than number. For example:
const sortNumbers = (arr) => {
return arr.sort();
}
console.log(sortNumbers([1, 11, 27, 2, 34, 123])); // [ 1, 11, 123, 2, 27, 34 ]
We need to use a compare function as a callback passed into the sort method to make sure that the actual numbers are treated properly.
// Try it out yourself before clicking on the solution tab!
To sort an array of objects by a certain property, we have to use the compare function as a parameter in the built-in sort method in JavaScript.
The compare function takes in two parameters: here they are named a
and b
. They represent two objects next to each other in our array. If a and b are both objects, we can use dot notation to access the property population
.
If we want to be sure that the array has objects sorted by population in increasing order, we evaluate a.population
- b.population
. If it’s -1, it will put the list in decreasing order by population. The opposite would put it in increasing order. If the expression happens to evaluate to 0, it means that the two patterns are equal to the other.
Create a Node class and a LinkedList class with these methods:
insertFirst(data)
insertLast(data)
getFirst()
getLast()
Are we to assume this is a singly-linked list that actually exists?
The first thing we need to investigate is how a linked list works. Once we have that figured out, it might be a lot easier to write out the code for it.
Linked lists are different from arrays in that they don’t require a continuous place of residence in memory. Linked Lists can be broken up into single nodes if needed as long as the linked list’s next
value is not null.
Let’s plan to initialize three variables: prev
as NULL, curr
as head, and next
as NULL. Iterate trough the Linked List. In a while loop, do the following.
next
= curr.next
curr.next
= prev
// Try it out yourself here before checking the solution!
We start with the Node class. It will have a data property and a next property. The next property acts as a pointer that will direct us to the next node in our linked list if it exists, or null.
For the Linked List class, we check for failures in our methods before we handle the success. With Linked Lists, we will check to see if the actual list exists by checking to see if the head exists and perform the appropriate logic for each method.
When we reverse a linked list, juggling variables around is the rule of the day. We have one variable, node, that is declared and then initialized to head. We declare tmp
and prev
without initializing them.
While the node exists, we redirect the pointers by reassigning variables. The result is a reversed linked list.
Using the Node and LinkedList classes that you created in the previous question, add methods to it so that, when given an kth-integer, you can delete that $kth$ node from the linked list
Is this a zero-based indexing?
When given K we have to be able to delete that node in a linked list. To handle edge cases, we need to have some knowledge of the size of the list, the node prior to the Kth node and the node after the Kth node. We essentially need to redirect the pointers for those nodes to not include the one we want to be deleted.
To do that, we’ll loop through the list, keep track of which node we’re on, and change the pointers to skip the Kth-node. It’ll still be in memory, ready to be written over, but it will be essentially deleted from our list.
// Try it out yourself here before checkin the solution!
Given a linked list, return true if the list is circular, false if it is not.
LinkedList()
A Boolean that tells us if the linked list is circular or not.
What does it mean for a linked list to be circular?
We will have two pointers: one slow and one fast. The fast one will move twice as much as the slow one on each iteration. If it comes to be that the fast.next.next
value doesn’t exist, we can assume it’s a linear linked list. If the slow pointer and the fast pointer ultimately end up equal, we know we have a circular component to our list.
// Try it out yourself here before checking the solution!
Here we declare and initialize two pointers, one slow and one fast, that are both pointed at the head. While the next two nodes exist, we’ll reassign the pointers: the slow will move to the next node and the fast will move two nodes.
If the slow ever is the same value as the fast, we have a circular linked list. If ever one of the two nodes past the current node doesn’t exist, we’ll break the loop and return false.
Congrats! You’ve gone through 10 JavaScript coding challenges! One of the best things to do when encountering a problem is to use Georges Polya’s practices. Once we understand the problem, we make a plan and try to reiterate an unsolved problem. This way, you are more likely to break down the problem into smaller manageable components.
Solving these problems takes practice. You’ll develop an intuition for algorithms the more time you put into practicing. So don’t worry if it doesn’t come to you right away. Keep practicing!
Educative’s course The Complete Guide to Modern JavaScript
walks you through the basics of the language and all the new features introduced up to 2020. After following this course, functions and variables let
, const
, generators, promises and async won’t be a problem anymore.
Join a community of more than 1.4 million readers. A free, bi-monthly email with a roundup of Educative's top articles and coding tips.