RSS Feed

The Complete SDE Interview Handbook

#ALGORITHM PATTERNS SUMMARY

#Two Pointers

  • Valid Palindrome, 3Sum
  • Use when: Sorted array, finding pairs, palindromes

#Sliding Window

  • Longest Substring Without Repeating Characters
  • Use when: Contiguous subarrays, substring problems

#Fast & Slow Pointers

  • Linked List Cycle, Middle of Linked List
  • Use when: Cycle detection, finding middle
  • Binary Search, First Bad Version
  • Use when: Sorted array, search space reduction

#BFS/DFS

  • Number of Islands, Clone Graph, Course Schedule
  • Use when: Tree/graph traversal, shortest path

#Dynamic Programming

  • Climbing Stairs, Coin Change, Maximum Subarray
  • Use when: Overlapping subproblems, optimization

#Backtracking

  • Generate combinations, permutations
  • Use when: Exploring all possibilities

#Stack

  • Valid Parentheses, Min Stack, Evaluate RPN
  • Use when: LIFO order, nested structures

#Hash Table

  • Two Sum, Valid Anagram, Group Anagrams
  • Use when: Fast lookups, counting, mapping

#Greedy

  • Best Time to Buy Stock, Longest Palindrome
  • Use when: Local optimal leads to global optimal

#TIME COMPLEXITY CHEAT SHEET

Pattern Time Space Example
Two Pointers O(n) O(1) Valid Palindrome
Sliding Window O(n) O(k) Longest Substring
Binary Search O(log n) O(1) Search Array
BFS/DFS O(V + E) O(V) Number of Islands
Dynamic Programming O(n²) O(n) Coin Change
Sorting O(n log n) O(1) 3Sum

#COMMON EDGE CASES

#Arrays

  • Empty array: []
  • Single element: [1]
  • All same elements: [1,1,1]
  • Negative numbers: [-1,-2,-3]

#Strings

  • Empty string: ""
  • Single character: "a"
  • All same characters: "aaa"
  • Special characters: "a!@#"

#Trees

  • Empty tree: null
  • Single node: root only
  • Linear tree: all left or all right
  • Complete/balanced tree

#Linked Lists

  • Empty list: null
  • Single node: head only
  • Cycle: last node points to previous
  • Even/odd length lists

#INTERVIEW TIPS

#Problem-Solving Process

  1. Clarify requirements (2-3 min)
    • Ask about edge cases
    • Confirm input/output format
    • Understand constraints
  2. Discuss approach (3-5 min)
    • Start with brute force
    • Identify pattern
    • Optimize solution
    • Analyze complexity
  3. Code solution (15-20 min)
    • Write clean, readable code
    • Handle edge cases
    • Use good variable names
    • Add comments for complex logic
  4. Test and verify (5 min)
    • Walk through examples
    • Check edge cases
    • Verify time/space complexity

#Communication Tips

  • Think out loud
  • Explain your approach before coding
  • Ask clarifying questions
  • Don't be silent while coding
  • Explain trade-offs
  • Off-by-one errors in loops

#1. Two Sum

Description: Find two numbers in array that add up to target Tags: Array, Hash Table

function twoSum(nums, target) {
    const map = new Map();
    for (let i = 0; i < nums.length; i++) {
        const complement = target - nums[i];
        if (map.has(complement)) {
            return [map.get(complement), i];
        }
        map.set(nums[i], i);
    }
}

#2. Valid Parentheses

Description: Check if string has valid parentheses pairs Tags: Stack, String

function isValid(s) {
    const stack = [];
    const pairs = { ')': '(', '}': '{', ']': '[' };

    for (let char of s) {
        if (char in pairs) {
            if (stack.pop() !== pairs[char]) return false;
        } else {
            stack.push(char);
        }
    }
    return stack.length === 0;
}


#3. Best Time to Buy and Sell Stock

Description: Find max profit from buying and selling stock once Tags: Array, Dynamic Programming

function maxProfit(prices) {
    let minPrice = prices[0];
    let maxProfit = 0;

    for (let i = 1; i < prices.length; i++) {
        if (prices[i] < minPrice) {
            minPrice = prices[i];
        } else {
            maxProfit = Math.max(maxProfit, prices[i] - minPrice);
        }
    }
    return maxProfit;
}

#4. Valid Palindrome

Description: Check if string is palindrome ignoring non-alphanumeric Tags: Two Pointers, String

function isPalindrome(s) {
    s = s.toLowerCase().replace(/[^a-z0-9]/g, '');
    let left = 0, right = s.length - 1;

    while (left < right) {
        if (s[left] !== s[right]) return false;
        left++;
        right--;
    }
    return true;
}


#5. Invert Binary Tree

Description: Invert a binary tree (swap left and right children) Tags: Tree, Depth-First Search, Breadth-First Search

function invertTree(root) {
    if (!root) return null;

    const left = invertTree(root.left);
    const right = invertTree(root.right);

    root.left = right;
    root.right = left;

    return root;
}

#6. Valid Anagram

Description: Check if two strings are anagrams Tags: Hash Table, String, Sorting

function isAnagram(s, t) {
    if (s.length !== t.length) return false;

    const count = {};
    for (let char of s) {
        count[char] = (count[char] || 0) + 1;
    }

    for (let char of t) {
        if (!count[char]) return false;
        count[char]--;
    }
    return true;
}


Description: Search target value in sorted array Tags: Array, Binary Search

function search(nums, target) {
    let left = 0, right = nums.length - 1;

    while (left <= right) {
        const mid = Math.floor((left + right) / 2);

        if (nums[mid] === target) return mid;
        else if (nums[mid] < target) left = mid + 1;
        else right = mid - 1;
    }
    return -1;
}

#8. Flood Fill

Description: Change color of connected pixels in 2D image Tags: Array, Depth-First Search, Breadth-First Search

function floodFill(image, sr, sc, color) {
    const originalColor = image[sr][sc];
    if (originalColor === color) return image;

    function dfs(r, c) {
        if (r < 0 || r >= image.length || c < 0 ||
            c >= image[0].length || image[r][c] !== originalColor) {
            return;
        }

        image[r][c] = color;
        dfs(r + 1, c);
        dfs(r - 1, c);
        dfs(r, c + 1);
        dfs(r, c - 1);
    }

    dfs(sr, sc);
    return image;
}


#9. Lowest Common Ancestor of BST

Description: Find LCA of two nodes in binary search tree Tags: Tree, Depth-First Search, Binary Search Tree

function lowestCommonAncestor(root, p, q) {
    while (root) {
        if (root.val > p.val && root.val > q.val) {
            root = root.left;
        } else if (root.val < p.val && root.val < q.val) {
            root = root.right;
        } else {
            return root;
        }
    }
}

#10. Balanced Binary Tree

Description: Check if binary tree is height-balanced Tags: Tree, Depth-First Search, Binary Tree

function isBalanced(root) {
    function checkHeight(node) {
        if (!node) return 0;

        const left = checkHeight(node.left);
        const right = checkHeight(node.right);

        if (left === -1 || right === -1 ||
            Math.abs(left - right) > 1) {
            return -1;
        }

        return Math.max(left, right) + 1;
    }

    return checkHeight(root) !== -1;
}


#11. Linked List Cycle

Description: Detect if linked list has a cycle Tags: Hash Table, Linked List, Two Pointers

function hasCycle(head) {
    let slow = head;
    let fast = head;

    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;

        if (slow === fast) {
            return true;
        }
    }

    return false;
}

#12. Implement Queue using Stacks

Description: Implement queue using only two stacks Tags: Stack, Design, Queue

class MyQueue {
    constructor() {
        this.inStack = [];
        this.outStack = [];
    }

    push(x) {
        this.inStack.push(x);
    }

    pop() {
        this.peek();
        return this.outStack.pop();
    }

    peek() {
        if (this.outStack.length === 0) {
            while (this.inStack.length > 0) {
                this.outStack.push(this.inStack.pop());
            }
        }
        return this.outStack[this.outStack.length - 1];
    }

    empty() {
        return this.inStack.length === 0 && this.outStack.length === 0;
    }
}


#13. First Bad Version

Description: Find first bad version using binary search Tags: Binary Search, Interactive

function firstBadVersion(n) {
    let left = 1, right = n;

    while (left < right) {
        const mid = Math.floor(left + (right - left) / 2);

        if (isBadVersion(mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    return left;
}

#14. Ransom Note

Description: Check if ransom note can be constructed from magazine Tags: Hash Table, String, Counting

function canConstruct(ransomNote, magazine) {
    const count = {};

    for (let char of magazine) {
        count[char] = (count[char] || 0) + 1;
    }

    for (let char of ransomNote) {
        if (!count[char]) return false;
        count[char]--;
    }

    return true;
}


#15. Climbing Stairs

Description: Count distinct ways to climb n stairs (1 or 2 steps) Tags: Math, Dynamic Programming, Memoization

function climbStairs(n) {
    if (n <= 2) return n;

    let prev2 = 1, prev1 = 2;

    for (let i = 3; i <= n; i++) {
        const current = prev1 + prev2;
        prev2 = prev1;
        prev1 = current;
    }

    return prev1;
}

#16. Longest Palindrome

Description: Find length of longest palindrome from string characters Tags: Hash Table, String, Greedy

function longestPalindrome(s) {
    const count = {};
    for (let char of s) {
        count[char] = (count[char] || 0) + 1;
    }

    let length = 0;
    let hasOdd = false;

    for (let freq of Object.values(count)) {
        length += Math.floor(freq / 2) * 2;
        if (freq % 2 === 1) hasOdd = true;
    }

    return length + (hasOdd ? 1 : 0);
}


#17. Reverse Linked List

Description: Reverse a singly linked list Tags: Linked List, Recursion

// Iterative
function reverseList(head) {
    let prev = null;
    let current = head;

    while (current) {
        const next = current.next;
        current.next = prev;
        prev = current;
        current = next;
    }

    return prev;
}

// Recursive
function reverseListRecursive(head) {
    if (!head || !head.next) return head;

    const newHead = reverseListRecursive(head.next);
    head.next.next = head;
    head.next = null;

    return newHead;
}

#18. Majority Element

Description: Find element that appears more than n/2 times Tags: Array, Hash Table, Divide and Conquer, Sorting, Counting

// Boyer-Moore Voting Algorithm
function majorityElement(nums) {
    let candidate = nums[0];
    let count = 1;

    for (let i = 1; i < nums.length; i++) {
        if (count === 0) {
            candidate = nums[i];
            count = 1;
        } else if (nums[i] === candidate) {
            count++;
        } else {
            count--;
        }
    }

    return candidate;
}


#19. Add Binary

Description: Add two binary strings and return sum as binary string Tags: Math, String, Bit Manipulation, Simulation

function addBinary(a, b) {
    let result = '';
    let carry = 0;
    let i = a.length - 1;
    let j = b.length - 1;

    while (i >= 0 || j >= 0 || carry) {
        const sum = carry +
                   (i >= 0 ? parseInt(a[i--]) : 0) +
                   (j >= 0 ? parseInt(b[j--]) : 0);

        result = (sum % 2) + result;
        carry = Math.floor(sum / 2);
    }

    return result;
}

#20. Diameter of Binary Tree

Description: Find diameter (longest path between any two nodes) Tags: Tree, Depth-First Search, Binary Tree

function diameterOfBinaryTree(root) {
    let maxDiameter = 0;

    function dfs(node) {
        if (!node) return 0;

        const left = dfs(node.left);
        const right = dfs(node.right);

        maxDiameter = Math.max(maxDiameter, left + right);

        return Math.max(left, right) + 1;
    }

    dfs(root);
    return maxDiameter;
}


#21. Middle of Linked List

Description: Find middle node of linked list Tags: Linked List, Two Pointers

function middleNode(head) {
    let slow = head;
    let fast = head;

    while (fast && fast.next) {
        slow = slow.next;
        fast = fast.next.next;
    }

    return slow;
}

#22. Maximum Depth of Binary Tree

Description: Find maximum depth of binary tree Tags: Tree, Depth-First Search, Breadth-First Search, Binary Tree

// Recursive DFS
function maxDepth(root) {
    if (!root) return 0;

    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

// Iterative BFS
function maxDepthBFS(root) {
    if (!root) return 0;

    const queue = [[root, 1]];
    let maxDepth = 0;

    while (queue.length > 0) {
        const [node, depth] = queue.shift();
        maxDepth = Math.max(maxDepth, depth);

        if (node.left) queue.push([node.left, depth + 1]);
        if (node.right) queue.push([node.right, depth + 1]);
    }

    return maxDepth;
}


#23. Contains Duplicate

Description: Check if array contains any duplicate values Tags: Array, Hash Table, Sorting

function containsDuplicate(nums) {
    const seen = new Set();

    for (let num of nums) {
        if (seen.has(num)) {
            return true;
        }
        seen.add(num);
    }

    return false;
}

// Alternative: One-liner
function containsDuplicateOneLiner(nums) {
    return new Set(nums).size !== nums.length;
}

#24. Maximum Subarray

Description: Find contiguous subarray with largest sum Tags: Array, Divide and Conquer, Dynamic Programming

// Kadane's Algorithm
function maxSubArray(nums) {
    let maxSoFar = nums[0];
    let maxEndingHere = nums[0];

    for (let i = 1; i < nums.length; i++) {
        maxEndingHere = Math.max(nums[i], maxEndingHere + nums[i]);
        maxSoFar = Math.max(maxSoFar, maxEndingHere);
    }

    return maxSoFar;
}


#25. Insert Interval

Description: Insert new interval into sorted non-overlapping intervals Tags: Array

function insert(intervals, newInterval) {
    const result = [];
    let i = 0;

    // Add all intervals before newInterval
    while (i < intervals.length && intervals[i][1] < newInterval[0]) {
        result.push(intervals[i]);
        i++;
    }

    // Merge overlapping intervals
    while (i < intervals.length && intervals[i][0] <= newInterval[1]) {
        newInterval[0] = Math.min(newInterval[0], intervals[i][0]);
        newInterval[1] = Math.max(newInterval[1], intervals[i][1]);
        i++;
    }
    result.push(newInterval);

    // Add remaining intervals
    while (i < intervals.length) {
        result.push(intervals[i]);
        i++;
    }

    return result;
}

#26. 01 Matrix

Description: Find distance to nearest 0 for each cell Tags: Array, Dynamic Programming, Breadth-First Search, Matrix

function updateMatrix(mat) {
    const rows = mat.length, cols = mat[0].length;
    const dist = Array(rows).fill().map(() => Array(cols).fill(Infinity));
    const queue = [];

    // Find all 0s and add to queue
    for (let i = 0; i < rows; i++) {
        for (let j = 0; j < cols; j++) {
            if (mat[i][j] === 0) {
                dist[i][j] = 0;
                queue.push([i, j]);
            }
        }
    }

    const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];

    while (queue.length > 0) {
        const [row, col] = queue.shift();

        for (const [dr, dc] of directions) {
            const newRow = row + dr;
            const newCol = col + dc;

            if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {
                if (dist[newRow][newCol] > dist[row][col] + 1) {
                    dist[newRow][newCol] = dist[row][col] + 1;
                    queue.push([newRow, newCol]);
                }
            }
        }
    }

    return dist;
}


#27. K Closest Points to Origin

Description: Find k closest points to origin (0,0) Tags: Array, Math, Divide and Conquer, Geometry, Sorting, Heap

function kClosest(points, k) {
    return points
        .map(point => ({
            point: point,
            distance: point[0] * point[0] + point[1] * point[1]
        }))
        .sort((a, b) => a.distance - b.distance)
        .slice(0, k)
        .map(item => item.point);
}

// Using Min Heap (more efficient for large datasets)
function kClosestHeap(points, k) {
    const heap = new MinHeap();

    for (const point of points) {
        const distance = point[0] * point[0] + point[1] * point[1];
        heap.insert([distance, point]);
    }

    const result = [];
    for (let i = 0; i < k; i++) {
        result.push(heap.extract()[1]);
    }

    return result;
}

#28. Longest Substring Without Repeating Characters

Description: Find length of longest substring without repeating characters Tags: Hash Table, String, Sliding Window

function lengthOfLongestSubstring(s) {
    const seen = new Set();
    let left = 0;
    let maxLength = 0;

    for (let right = 0; right < s.length; right++) {
        while (seen.has(s[right])) {
            seen.delete(s[left]);
            left++;
        }

        seen.add(s[right]);
        maxLength = Math.max(maxLength, right - left + 1);
    }

    return maxLength;
}


#29. 3Sum

Description: Find all unique triplets that sum to zero Tags: Array, Two Pointers, Sorting

function threeSum(nums) {
    nums.sort((a, b) => a - b);
    const result = [];

    for (let i = 0; i < nums.length - 2; i++) {
        if (i > 0 && nums[i] === nums[i - 1]) continue;

        let left = i + 1;
        let right = nums.length - 1;

        while (left < right) {
            const sum = nums[i] + nums[left] + nums[right];

            if (sum === 0) {
                result.push([nums[i], nums[left], nums[right]]);

                while (left < right && nums[left] === nums[left + 1]) left++;
                while (left < right && nums[right] === nums[right - 1]) right--;

                left++;
                right--;
            } else if (sum < 0) {
                left++;
            } else {
                right--;
            }
        }
    }

    return result;
}

#30. Binary Tree Level Order Traversal

Description: Return level order traversal of binary tree Tags: Tree, Breadth-First Search, Binary Tree

function levelOrder(root) {
    if (!root) return [];

    const result = [];
    const queue = [root];

    while (queue.length > 0) {
        const levelSize = queue.length;
        const currentLevel = [];

        for (let i = 0; i < levelSize; i++) {
            const node = queue.shift();
            currentLevel.push(node.val);

            if (node.left) queue.push(node.left);
            if (node.right) queue.push(node.right);
        }

        result.push(currentLevel);
    }

    return result;
}


#31. Clone Graph

Description: Clone undirected connected graph Tags: Hash Table, Depth-First Search, Breadth-First Search, Graph

function cloneGraph(node) {
    if (!node) return null;

    const visited = new Map();

    function dfs(node) {
        if (visited.has(node)) {
            return visited.get(node);
        }

        const clone = new Node(node.val);
        visited.set(node, clone);

        for (const neighbor of node.neighbors) {
            clone.neighbors.push(dfs(neighbor));
        }

        return clone;
    }

    return dfs(node);
}

#32. Evaluate Reverse Polish Notation

Description: Evaluate arithmetic expression in postfix notation Tags: Array, Math, Stack

function evalRPN(tokens) {
    const stack = [];
    const operators = {
        '+': (a, b) => a + b,
        '-': (a, b) => a - b,
        '*': (a, b) => a * b,
        '/': (a, b) => Math.trunc(a / b)
    };

    for (const token of tokens) {
        if (token in operators) {
            const b = stack.pop();
            const a = stack.pop();
            stack.push(operators[token](a, b));
        } else {
            stack.push(parseInt(token));
        }
    }

    return stack[0];
}


#33. Course Schedule

Description: Check if all courses can be finished given prerequisites Tags: Depth-First Search, Breadth-First Search, Graph, Topological Sort

function canFinish(numCourses, prerequisites) {
    const graph = Array(numCourses).fill().map(() => []);
    const inDegree = Array(numCourses).fill(0);

    // Build graph and calculate in-degrees
    for (const [course, prereq] of prerequisites) {
        graph[prereq].push(course);
        inDegree[course]++;
    }

    // Kahn's algorithm for topological sort
    const queue = [];
    for (let i = 0; i < numCourses; i++) {
        if (inDegree[i] === 0) {
            queue.push(i);
        }
    }

    let completed = 0;
    while (queue.length > 0) {
        const course = queue.shift();
        completed++;

        for (const nextCourse of graph[course]) {
            inDegree[nextCourse]--;
            if (inDegree[nextCourse] === 0) {
                queue.push(nextCourse);
            }
        }
    }

    return completed === numCourses;
}

#34. Implement Trie (Prefix Tree)

Description: Implement trie data structure for string operations Tags: Hash Table, String, Design, Trie

class TrieNode {
    constructor() {
        this.children = {};
        this.isEndOfWord = false;
    }
}

class Trie {
    constructor() {
        this.root = new TrieNode();
    }

    insert(word) {
        let node = this.root;
        for (const char of word) {
            if (!node.children[char]) {
                node.children[char] = new TrieNode();
            }
            node = node.children[char];
        }
        node.isEndOfWord = true;
    }

    search(word) {
        let node = this.root;
        for (const char of word) {
            if (!node.children[char]) {
                return false;
            }
            node = node.children[char];
        }
        return node.isEndOfWord;
    }

    startsWith(prefix) {
        let node = this.root;
        for (const char of prefix) {
            if (!node.children[char]) {
                return false;
            }
            node = node.children[char];
        }
        return true;
    }
}


#35. Coin Change

Description: Find minimum coins needed to make amount Tags: Array, Dynamic Programming, Breadth-First Search

function coinChange(coins, amount) {
    const dp = Array(amount + 1).fill(Infinity);
    dp[0] = 0;

    for (let i = 1; i <= amount; i++) {
        for (const coin of coins) {
            if (coin <= i) {
                dp[i] = Math.min(dp[i], dp[i - coin] + 1);
            }
        }
    }

    return dp[amount] === Infinity ? -1 : dp[amount];
}

#36. Product of Array Except Self

Description: Return array where each element is product of all others Tags: Array, Prefix Sum

function productExceptSelf(nums) {
    const result = Array(nums.length);

    // Forward pass: left products
    result[0] = 1;
    for (let i = 1; i < nums.length; i++) {
        result[i] = result[i - 1] * nums[i - 1];
    }

    // Backward pass: multiply by right products
    let rightProduct = 1;
    for (let i = nums.length - 1; i >= 0; i--) {
        result[i] *= rightProduct;
        rightProduct *= nums[i];
    }

    return result;
}


#37. Min Stack

Description: Stack supporting push, pop, top, and getMin in O(1) Tags: Stack, Design

class MinStack {
    constructor() {
        this.stack = [];
        this.minStack = [];
    }

    push(val) {
        this.stack.push(val);
        if (this.minStack.length === 0 || val <= this.getMin()) {
            this.minStack.push(val);
        }
    }

    pop() {
        const popped = this.stack.pop();
        if (popped === this.getMin()) {
            this.minStack.pop();
        }
        return popped;
    }

    top() {
        return this.stack[this.stack.length - 1];
    }

    getMin() {
        return this.minStack[this.minStack.length - 1];
    }
}

#38. Validate Binary Search Tree

Description: Check if binary tree is valid BST Tags: Tree, Depth-First Search, Binary Search Tree, Binary Tree

function isValidBST(root) {
    function validate(node, min, max) {
        if (!node) return true;

        if (node.val <= min || node.val >= max) {
            return false;
        }

        return validate(node.left, min, node.val) &&
               validate(node.right, node.val, max);
    }

    return validate(root, -Infinity, Infinity);
}


#39. Number of Islands

Description: Count number of islands in 2D binary grid Tags: Array, Depth-First Search, Breadth-First Search, Union Find, Matrix

function numIslands(grid) {
    if (!grid || grid.length === 0) return 0;

    const rows = grid.length;
    const cols = grid[0].length;
    let count = 0;

    function dfs(r, c) {
        if (r < 0 || r >= rows || c < 0 || c >= cols || grid[r][c] === '0') {
            return;
        }

        grid[r][c] = '0'; // Mark as visited

        dfs(r + 1, c);
        dfs(r - 1, c);
        dfs(r, c + 1);
        dfs(r, c - 1);
    }

    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (grid[r][c] === '1') {
                count++;
                dfs(r, c);
            }
        }
    }

    return count;
}

#40. Rotting Oranges

Description: Find time for all oranges to rot (BFS simulation) Tags: Array, Breadth-First Search, Matrix

function orangesRotting(grid) {
    const rows = grid.length;
    const cols = grid[0].length;
    const queue = [];
    let freshCount = 0;

    // Find all rotten oranges and count fresh ones
    for (let r = 0; r < rows; r++) {
        for (let c = 0; c < cols; c++) {
            if (grid[r][c] === 2) {
                queue.push([r, c]);
            } else if (grid[r][c] === 1) {
                freshCount++;
            }
        }
    }

    if (freshCount === 0) return 0;

    const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
    let minutes = 0;

    while (queue.length > 0 && freshCount > 0) {
        const size = queue.length;

        for (let i = 0; i < size; i++) {
            const [r, c] = queue.shift();

            for (const [dr, dc] of directions) {
                const nr = r + dr;
                const nc = c + dc;

                if (nr >= 0 && nr < rows && nc >= 0 && nc < cols &&
                    grid[nr][nc] === 1) {
                    grid[nr][nc] = 2;
                    queue.push([nr, nc]);
                    freshCount--;
                }
            }
        }
        minutes++;
    }

    return freshCount === 0 ? minutes : -1;
}


Tags: #LeetCode #TechnicalInterview #SoftwareEngineer #CodingInterview #AlgorithmsAndDataStructures