DEV Community

Cover image for Why JavaScript is actually a great LeetCode/Interview language
Braeden Smith
Braeden Smith

Posted on • Edited on

Why JavaScript is actually a great LeetCode/Interview language

In reality, the best language is the one you're comfortable with.

But if you're debating learning a non-strictly typed language, or stuck between several choices, I want to present a couple of reasons why JS might be worth a try.

Everyone is on the LeetCode grind these days.

If you're unfamiliar with LeetCode, it's a way to practice interview-type coding challenges in a short time frame. This article applies to actual interview services too, whether that's HackerRank, CodeSignal, HireVue, or any of the other numerous testing services.

For beginners, it's often parroted that Python, Java and C++ are the "big 3" to learn for LeetCode.

It's often said that C++/Java are great choices because they're super fast, have wide standard libraries, and strictly typed. C++ has a bit more convolution with memory management and iterators, but trades that for speed. Java is notoriously verbose, which is often against the spirit of fast iteration during interviews.

On the other hand, people often like Python since it's similar to writing pseudocode, it has a super beginner friendly community, and is fast to iterate upon.

I'm going to present some reasons (in no particular order) why JavaScript might be the best of both worlds for coding challenges (but especially as an alternative to Python).

I'm going to avoid dissing other languages in my reasoning, because I'm not quite as familiar and wouldn't want to misspeak about features.

#1) - Everything is objects (and that's awesome)

const object = {"key": "value"}

object.key // 'value' -- O(1) access/insertion time obv.
object.newKey = 'newValue'
object['key'] == object.key // true
// Easy to iterate (and it has fixed ordering)
Object.entries(object) // [ [ 'key', 'value' ], ... ]
Enter fullscreen mode Exit fullscreen mode

Objects are awesome, flexible, and arguably the most important data association in software development.

I'd argue that "HashMap" type data structures are more valuable and more widely used than arrays. Fun fact: In JS typeof([1]) // 'object' -- even arrays are objects, just with some special additional properties.

But essentially we can use them as replacements to Sets/Maps/Dictionaries in other languages (which I'm sure a crazy high percentage of LeetCode-type problems require). And for problems that need to maintain insertion order we can use Map() and Set() in JS.

We can also easily use objects to represent Linked Lists, Trees, Graphs, Tries and more! This is essential when problems require to build out more complex algorithms.

let graph = {
'1': {
   edges: [2,4,5]
},
'2': {
   edges: [...]
}
....
}

let trie = { 
a: {
   b: { c: {} },
   d: {}
}
Enter fullscreen mode Exit fullscreen mode

#2) Sometimes strict, static typing is awesome (but not for speed)

> [] + []
''
> {} + []
0
> [] + {}
'[object Object]'
// wtf https://www.destroyallsoftware.com/talks/wat
Enter fullscreen mode Exit fullscreen mode

For real maintainable, testable, reliable code, it's almost always to have some typing assistance, whether that's a bit lighter (TypeScript) or super heavy (Rust).

But oftentimes that comes with the trade-off of fast iteration (or writing nothing but auto).

Learning how type coercion and non-static typing works in JS and similar scripting languages (Python, Ruby) makes it super easy to do fast tricks.

Essentially our JS engine does a best-effort type coercion when we're comparing or operating different types (eg. Number, String, Object, Array) -- that can give us some initially strange side effects. But let's show an example of how we can use this to our advantage!

// Do a frequency count on an array 'a'
// and store it in a object 'o' {key: count}
const o = {}
a.forEach(e => { o[e] = o[e] + 1 || 1 } )
// if o[e] doesn't exist, it's 'falsy'
// we short-circuit logical OR to return 1
Enter fullscreen mode Exit fullscreen mode

I use this code basically all the time -- but there's plenty of other instances where this type coersion (especially knowing 0, '', null, undefined are all fasly values).

Reason #3) JSON = JavaScript Object Notation (and the web <3s it)

This advantage applies less to LeetCode problems, but more to take-home assessments. Build a small app to hit and API and do some data manipulation and POST it back to another endpoint.

This is what JS was built for, manipulating and handling data between web services. Almost every API or take-home assessment will involve JSON in some way or another -- and the built-in methods like JSON.stringify() and JSON.parse() make it a breeze.

From personal experience, I've done assessments with HubSpot and many others -- their whole focus is on real-world work for their assessment -- nothing is more real-world then GET requests and parsing JSON.

I was able to work extremely fast through the problems because I don't have to think twice about setting up libraries or schemas -- I just use Axios/Node-fetch and get back a fully usable object that I can manipulate to my heart's content.

And even for testing, being able to just paste JSON into an IDE and it immediately being a valid object to work with is extremely valuable.

#4) Built in array methods make life easy

Array questions are just about the most common input data structure, so you'll be manipulating and iterating through them often.

I'll just quickly enumerate some awesome array methods that I find myself using all the time in LeetCode and interviews (interviewers are often impressed by how quick and easy it makes certain problems).

Basic data manipulation (we can reduce mental complexity and use arrays as stacks and queues in JS)

1) pop()

['1','2'].pop() // a = ['1'], returns '2'
Enter fullscreen mode Exit fullscreen mode

2) push()

['1'].push('2') // a = ['1','2']
Enter fullscreen mode Exit fullscreen mode

3) shift()

['1','2'].shift() // a = ['2'], returns '1'
Enter fullscreen mode Exit fullscreen mode

4) unshift()

['2'].unshift('1') // a = ['1','2']
Enter fullscreen mode Exit fullscreen mode

5) slice()

[1,2,3].slice(1,2) // a = [2, 3]
// selects from index start -> end (optional) -- negative start index works too
Enter fullscreen mode Exit fullscreen mode

Some iterative array manipulation (by order of most useful)

1) forEach()

a.forEach((e,i) => console.log(e, i)) // [1,2,3] -> prints 1 0 2 1 3 2
// iterates through each element
Enter fullscreen mode Exit fullscreen mode

2) map()

a.map(e => e+1) // [1,2,3] -> [2,3,4]
// returns a new array with per element manipulation
Enter fullscreen mode Exit fullscreen mode

3) reduce()

a.reduce((accum,e) => accum += e, 0) // [1,2,3] -> 6
// returns value that results from the reduction
Enter fullscreen mode Exit fullscreen mode

4) sort()

a.sort((a,b) => b-a) // [1,2,3] -> [3,2,1] 
// returns a new array sorted based on the call-back comparison
Enter fullscreen mode Exit fullscreen mode

5) filter()

a.filter(e => e%2!==0) // [1,2,3] -> [1,3] 
// returns a new array based on elements where the return is truthy
Enter fullscreen mode Exit fullscreen mode

Extras

1) Turning strings into arrays and vice-versa (super common)

> "string".split('')
[ 's', 't', 'r', 'i', 'n', 'g' ]
> [ 's', 't', 'r', 'i', 'n', 'g' ].join(' ')
's t r i n g'
Enter fullscreen mode Exit fullscreen mode

2) reverse()

[1, 2, 3].reverse() -> returns [3,2,1]
Enter fullscreen mode Exit fullscreen mode

3) every()

a.every(e => e > 0) // [1,2,3] -> true
// [-1, 2, 3] -> false 
// returns true if every element evaluates to true for the expression
Enter fullscreen mode Exit fullscreen mode

4) some()

a.some(e => e > 4) // [1,2,3] -> false 
// returns true if any element evaluates true for the expression
Enter fullscreen mode Exit fullscreen mode

Read about every array method here

#5) JavaScript execution (V8) is ridiculously quick

Language specific time-outs are supposed to be adjusted to fit the execution model. But I've heard on the internet and from friends, sometimes you'll hit the optimal solution in HackerRank, but still get TLE (time limit exceeded) timeouts for larger test cases in Python.

Worry no longer about execution on larger datasets -- you'll be competing speed-wise with C++ and Java when you use JavaScript (where the V8 JavaScript engine reigns supreme (Chrome, Node.js)).

Essentially if you're able to get an optimal solution, or even something close to it, you'll get through all hidden test cases from a timing perspective.

JS vs Python
JS vs C++
JS vs Java

Misc advantages:

These don't necessarily fit neatly in a category, but I felt it was important to bring up these positives.

1) Object destructuringconst { result } = { result: "answer" }
2) Optional chaining animal?.color?.hexcode
3) NPM/Yarn -- package.json and large access to libraries for take-home assessments, make package managment a breeze
4) Spread operator Math.max(...a)

A few downfalls or dislikes:

1) Lack of heap structure (at least built-in)
2) Direct string manipulation feels hacky: charAt(), split(), splice()
3) Array slicing feels less clean than Python implementations.

Thanks for reading! Let me know if you have any thoughts, why JS is great or not-great for coding interviews/LeetCode!

Top comments (2)

Collapse
 
manoharreddyporeddy profile image
Manohar Reddy Poreddy

Heap DS is there.
I have asked them last year
We can use github.com/datastructures-js/prior...
See FAQ page - support.leetcode.com/hc/en-us/arti...

Collapse
 
kamrulsh profile image
Kamrul Islam Shahin

Good article. I use javascript all the time at leetcode. 🚀