Array(cols).fill(0)); // correct // const bad = new Array(rows).fill(new Array(cols).fill(0)); // WRONG — all rows share memory"> Array(cols).fill(0)); // correct // const bad = new Array(rows).fill(new Array(cols).fill(0)); // WRONG — all rows share memory"> Array(cols).fill(0)); // correct // const bad = new Array(rows).fill(new Array(cols).fill(0)); // WRONG — all rows share memory">
| Operation | Complexity |
|---|---|
| Array push/pop (end) | O(1) |
| Array shift/unshift (start) | O(n) |
| Array access by index | O(1) |
| Array includes/indexOf | O(n) |
| Map/Set get/set/has/delete | O(1) average |
| Array sort | O(n log n) |
| Array slice/splice | O(n) |
// interview patterns
// Queue — JS has no built-in queue; array shift() is O(n), fine for interview-scale input
const queue: number[] = [];
queue.push(1); // enqueue
queue.shift(); // dequeue
// Min-heap / priority queue — no built-in. Two options in an interview:
// 1) Say explicitly: "TS has no built-in heap, I'd normally reach for a library
// like `heap-js`; here's how I'd implement one manually if needed."
// 2) For small inputs, sort an array repeatedly (state the O(n log n) per op cost).
// 2D array init — classic mistake: Array(n).fill([]) shares ONE array reference
const grid = Array.from({ length: rows }, () => Array(cols).fill(0)); // correct
// const bad = new Array(rows).fill(new Array(cols).fill(0)); // WRONG — all rows share memory
// type narrowing
function process(input: string | number) {
if (typeof input === "string") {
return input.toUpperCase(); // TS knows it's a string here
}
return input.toFixed(2); // TS knows it's a number here
}
// Array.isArray, instanceof, and 'in' also narrow types
if (Array.isArray(val)) { /* val is treated as an array */ }
if (node instanceof TreeNode) { /* ... */ }
Pattern: Hash map | O(n) time, O(n) space
function twoSum(nums: number[], target: number): number[] {
const seen = new Map<number, number>();
for (let i = 0; i < nums.length; i++) {
const complement = target - nums[i];
if (seen.has(complement)) return [seen.get(complement)!, i];
seen.set(nums[i], i);
}
return [];
}
Pattern: Stack | O(n) time, O(n) space
function isValid(s: string): boolean {
const stack: string[] = [];
const pairs: Record<string, string> = { ")": "(", "]": "[", "}": "{" };
for (const c of s) {
if (c === "(" || c === "[" || c === "{") {
stack.push(c);
} else {
if (stack.pop() !== pairs[c]) return false;
}
}
return stack.length === 0;
}
Pattern: Set | O(n) time, O(n) space
function containsDuplicate(nums: number[]): boolean {
return new Set(nums).size !== nums.length;
}
Pattern: Dynamic programming (running optimum) | O(n) time, O(1) space
function maxSubArray(nums: number[]): number {
let maxSoFar = nums[0];
let currentSum = nums[0];
for (let i = 1; i < nums.length; i++) {
currentSum = Math.max(nums[i], currentSum + nums[i]);
maxSoFar = Math.max(maxSoFar, currentSum);
}
return maxSoFar;
}
Pattern: Pointer manipulation | O(n) time, O(1) space
class ListNode {
val: number;
next: ListNode | null;
constructor(val: number, next: ListNode | null = null) {
this.val = val;
this.next = next;
}
}
function reverseList(head: ListNode | null): ListNode | null {
let prev: ListNode | null = null;
let curr = head;
while (curr !== null) {
const next = curr.next;
curr.next = prev;
prev = curr;
curr = next;
}
return prev;
}
Pattern: Sort + greedy sweep | O(n log n) time, O(n) space