Day 1: JS Essentials for DSA
DAY 1 / 30 · WEEK 1
Goal of the day
Section titled “Goal of the day”- Read and write arrays and objects fast, without hesitating over syntax.
- Use destructuring and the spread operator confidently — they show up in almost every interview solution.
- Know which array operations are cheap (O(1)) and which are expensive (O(n)), before you even get to Big-O on Day 2.
Concept
Section titled “Concept”Think of an array like a row of numbered lockers at a gym. Each locker has a fixed position (its index), so you can open any locker instantly if you know its number — that’s why arr[2] is instant (O(1)).
The four basic ways to add/remove elements all come down to one question: does anything else have to move?
push(x)— addxat the end. Nothing else moves. O(1).pop()— remove the last element. Nothing else moves. O(1).unshift(x)— addxat the front. Every other element has to shift one locker to the right first, to make room. O(n).shift()— remove the first element. Every remaining element has to shift one locker to the left, to close the gap. O(n).
Destructuring is a shortcut for pulling values out of an array into named variables in one line, instead of writing arr[0], arr[1] separately — that part really is free, it’s just reading. Spread (...) goes the other way — it builds a whole new array by copying every value out of the old one. That copy is still real work: O(n), same cost as writing the loop yourself. Spread doesn’t add a new capability, it’s just a cleaner way to write a copy loop you could’ve written by hand.
Diagram
Section titled “Diagram”Running example: arr = [4, 7, 2, 9, 5]
Choose an operation to animate it.
elements touched: —
const arr = [4, 7, 2, 9, 5];
arr.push(6); // [4, 7, 2, 9, 5, 6] — O(1)arr.pop(); // [4, 7, 2, 9, 5] — O(1)
arr.unshift(1); // [1, 4, 7, 2, 9, 5] — O(n)arr.shift(); // [4, 7, 2, 9, 5] — O(n)
const [first, second] = arr; // destructuring — O(1) per bindingconst copy = [...arr]; // spread copy — O(n), same cost as a manual loopDry run: array mutations
Section titled “Dry run: array mutations”| Step | Code | arr | a, b, c, d, e | merged |
|---|---|---|---|---|
| 1 | const arr = [4,7,2,9,5] |
[4,7,2,9,5] |
— | — |
| 2 | arr.push(6) |
[4,7,2,9,5,6] |
— | — |
| 3 | arr.pop() |
[4,7,2,9,5] |
— | — |
| 4 | arr.unshift(1) |
[1,4,7,2,9,5] |
— | — |
| 5 | arr.shift() |
[4,7,2,9,5] |
— | — |
| 6 | const [a,b,c,d,e] = arr |
[4,7,2,9,5] |
4, 7, 2, 9, 5 | — |
| 7 | const merged = [...arr, 6] |
[4,7,2,9,5] |
4, 7, 2, 9, 5 | [4,7,2,9,5,6] |
Complexity
Section titled “Complexity”| Operation | Time | Space | Why |
|---|---|---|---|
Read by index arr[i] |
O(1) | O(1) | Contiguous memory — index math jumps straight there. |
| Destructure n values* | O(n) | O(1) extra | Has to read n slots, one per variable. |
Spread copy [...arr] |
O(n) | O(n) | Every element must be copied into the new array. |
push / pop (end) |
O(1)† | O(1) | No shifting — just add/remove the last slot. |
unshift / shift (start) |
O(n) | O(1) | Every remaining element has to shift one slot over. |
*Here n is the number of variables you’re destructuring, not the array’s length — const [a, b] = hugeArray is O(2), not O(hugeArray.length). †Amortized — occasionally the engine has to grow the underlying array, but on average it’s O(1).
Interview corner
Section titled “Interview corner”What’s the difference between rest and spread syntax? Same ... symbol, opposite direction: spread expands an array/object into individual elements ([...arr]); rest collects individual elements into an array (function f(...args)).
Does destructuring work on objects too? Yes — const {a, b} = obj matches by key name instead of position. You can rename with const {a: renamed} = obj, and set a default with const {a = 5} = obj.
Is [...arr] a deep copy or a shallow copy? Shallow. If arr contains objects or nested arrays, the copy shares references to those same inner objects — mutating a nested object still affects both arrays.
Why is unshift slower than push on a big array? push just writes to the next free slot. unshift has to shift every existing element one position to the right first, which is O(n).
What happens if you destructure more variables than the array has? The extra variables are undefined — no error is thrown.
How to talk through it out loud: say the plan before you type: “I’ll destructure the first two values since I only need those, then use spread to build a new array without mutating the input — that keeps this O(n) instead of accidentally O(n²) from copying in a loop.” Naming the shallow-copy gotcha unprompted is a strong signal to an interviewer that you’ve been burned by it before.
Practice problems
Section titled “Practice problems”All three below are warm-ups (Easy) — Day 1 is about getting comfortable with the syntax. Real easy → medium pattern problems start from Day 3 onward, once we’ve built up more tools.
1. Concatenation of Array — Easy
Section titled “1. Concatenation of Array — Easy”LeetCode: Concatenation of Array
Given an array nums, return an array ans of length 2n where ans is nums concatenated with itself.
Show solution
function getConcatenation(nums) { return [...nums, ...nums];}2. Running Sum of 1d Array — Easy
Section titled “2. Running Sum of 1d Array — Easy”LeetCode: Running Sum of 1d Array
Given an array nums, return a new array where each element is the sum of itself and every element before it.
Show solution
function runningSum(nums) { const result = []; let total = 0; // .entries() yields [index, value] pairs — a natural fit for destructuring. for (const [i, n] of nums.entries()) { total += n; result[i] = total; } return result;}3. Shuffle the Array — Easy
Section titled “3. Shuffle the Array — Easy”Given nums = [x1,...,xn, y1,...,yn], return the array in the shuffled form [x1,y1,x2,y2,...,xn,yn].
Show solution
function shuffle(nums, n) { const result = []; for (let i = 0; i < n; i++) { result.push(nums[i], nums[i + n]); } return result;}