Lv.1 Flashcards

Lv.1 problems of Firecode.io (17 cards)

1
Q

Bubble Sort

Write a method that takes in an array of ints and uses the Bubble Sort algorithm to sort the array β€˜in place’ in ascending order. The method should return the same, in-place sorted array.

/**
 * Sorts an array of integers in-place using the Bubble Sort algorithm.
 * @param {number[]} arr - The array of integers to sort.
 * @returns {number[]} - The sorted array (same reference, sorted in-place).
 */
function bubbleSort(arr) {
  // TODO: Implement Bubble Sort here
  return arr;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1 (Exploratory)
1. Think of the way bubbles rise to the top in water. Imagine that bigger numbers should β€œbubble” toward the end of the array.
2. You’ll need nested loops. Why might we need to loop inside a loop?
3. Focus on comparing adjacent elements.

🧩 Level 2 (Guided Nudges)
4. If the current element is greater than the next one, you probably want to swap them.
5. Repeat the process, reducing the inner loop range with each outer loop iteration – why might that be helpful?

πŸ”§ Level 3 (Practical Tips)
6. You can use a variable like temp to swap two array elements.
7. After each outer loop iteration, the largest unsorted element will be at the end.
8. Try optimizing by using a swapped flag. If nothing swapped in a pass, the array might already be sorted!

// --- Test Cases ---

function arraysEqual(a, b) {
  return Array.isArray(a) &&
    Array.isArray(b) &&
    a.length === b.length &&
    a.every((val, index) => val === b[index]);
}

function testBubbleSort() {
  const testCases = [
    { input: [], expected: [] },
    { input: [1], expected: [1] },
    { input: [2, 1], expected: [1, 2] },
    { input: [5, 2, 9, 1, 5, 6], expected: [1, 2, 5, 5, 6, 9] },
    { input: [3, -2, -1, 0, 2], expected: [-2, -1, 0, 2, 3] },
    { input: [10, 9, 8, 7], expected: [7, 8, 9, 10] },
    { input: [1, 2, 3, 4, 5], expected: [1, 2, 3, 4, 5] }, // already sorted
    { input: [5, 4, 3, 2, 1, 0], expected: [0, 1, 2, 3, 4, 5] }, // reverse order
    { input: [2, 3, 2, 3, 1], expected: [1, 2, 2, 3, 3] } // duplicates
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = bubbleSort([...input]); // Use spread to avoid mutating test input
    const passed = arraysEqual(result, expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input:    ${input}`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got:      ${result}`);
    }
  });
}

// Run the tests
testBubbleSort();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/sort-an-array/description/

A

βœ… JavaScript Solution

/**
 * Sorts the array in-place using Bubble Sort algorithm.
 * @param {number[]} arr - The array of integers to sort.
 * @returns {number[]} The sorted array (same reference as input).
 */
function bubbleSort(arr) {
  const n = arr.length;
  let swapped;

  for (let i = 0; i < n - 1; i++) {
    swapped = false;

    for (let j = 0; j < n - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        // Swap elements
        const temp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = temp;
        swapped = true;
      }
    }

    // Optimization: break early if no swaps occurred
    if (!swapped) break;
  }

  return arr;
}

// Example usage:
const numbers = [64, 34, 25, 12, 22, 11, 90];
console.log(bubbleSort(numbers)); // [11, 12, 22, 25, 34, 64, 90]

πŸ•’ Time & Space Complexity
Time Complexity:
Worst-case: O(nΒ²) β†’ when the array is in reverse order.
Best-case (optimized version): O(n) β†’ when the array is already sorted.
Average-case: O(nΒ²).

Space Complexity: O(1) β€” in-place sorting with no additional memory used.

βœ… Alternate Approaches (Educational)
| Built-in .sort() | Depends on engine (usually TimSort) | Very optimized in real apps |

πŸ“˜ Summary
* Use Bubble Sort as a stepping stone to understand how sorting works.
* You compare adjacent values and swap them if needed.
* It’s inefficient for large data sets but great for learning.
* Consider alternate sorting methods for real-world applications.

Algorithm | Time Complexity | Notes |
| β€”β€”β€”β€”β€”β€” | ———————————– | β€”β€”β€”β€”β€”β€”β€”β€”β€” |
| Quick Sort | O(n log n) avg | Efficient but not stable |
| Merge Sort | O(n log n) | Stable but not in-place |
| Built-in .sort() | Depends on engine (usually TimSort) | Very optimized in real apps |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Flip It!

You are given an m x n 2D image matrix where each integer represents a pixel. Flip it in-place along its vertical axis.

/**
 * Flips the given image matrix in-place along its vertical axis.
 * @param {number[][]} matrix - 2D array representing the image pixels.
 * @returns {number[][]} - The same matrix, flipped in-place.
 */
function flipImageVertically(matrix) {
  // TODO: Implement in-place vertical flip
  return matrix;
}

πŸͺœ Stepper Hints
πŸ” Level 1 (Vague + Exploratory)
1. Think about how a mirror would reflect a row of numbers.
2. Can you find a way to reverse a list without using .reverse()?
3. What happens if you only flip the first and last elements of a row?

🧩 Level 2 (Nudges)
4. You’ll need to loop over each row of the matrix.
5. Inside each row, think about how you’d swap elements from both ends moving inward.

πŸ”§ Level 3 (Closer to Code)
6. Use two pointers: one starting at the left (i), one at the right (j).
7. Swap row[i] with row[j] and move i++ and j– until they meet.
8. Don’t forget: you’re modifying each row in-place.

// --- Helper to compare two 2D matrices ---
function matricesEqual(a, b) {
  if (!Array.isArray(a) || !Array.isArray(b)) return false;
  if (a.length !== b.length) return false;
  for (let i = 0; i < a.length; i++) {
    if (!Array.isArray(a[i]) || !Array.isArray(b[i])) return false;
    if (a[i].length !== b[i].length) return false;
    for (let j = 0; j < a[i].length; j++) {
      if (a[i][j] !== b[i][j]) return false;
    }
  }
  return true;
}

// --- Test cases ---
function testFlipImageVertically() {
  const testCases = [
    {
      input: [],
      expected: []
    },
    {
      input: [[]],
      expected: [[]]
    },
    {
      input: [[1]],
      expected: [[1]]
    },
    {
      input: [
        [1, 2],
        [3, 4]
      ],
      expected: [
        [2, 1],
        [4, 3]
      ]
    },
    {
      input: [
        [1, 2, 3],
        [4, 5, 6]
      ],
      expected: [
        [3, 2, 1],
        [6, 5, 4]
      ]
    },
    {
      input: [
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12]
      ],
      expected: [
        [4, 3, 2, 1],
        [8, 7, 6, 5],
        [12, 11, 10, 9]
      ]
    },
  ];

  testCases.forEach(({ input, expected }, index) => {
    // Deep copy to avoid mutating original test input in tests
    const inputCopy = input.map(row => row.slice());
    const result = flipImageVertically(inputCopy);
    const passed = matricesEqual(result, expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log('Input:');
      console.table(input);
      console.log('Expected:');
      console.table(expected);
      console.log('Got:');
      console.table(result);
    }
  });
}

// Run tests
testFlipImageVertically();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/flipping-an-image/

A

βœ… JavaScript Solution

/**
 * Flips a 2D image in-place along its vertical axis.
 * @param {number[][]} matrix - 2D image matrix
 * @returns {number[][]} The same matrix flipped horizontally row-wise.
 */
function flipImageVertically(matrix) {
  for (let row of matrix) {
    let left = 0;
    let right = row.length - 1;

    while (left < right) {
      // Swap left and right elements
      const temp = row[left];
      row[left] = row[right];
      row[right] = temp;

      left++;
      right--;
    }
  }

  return matrix;
}

// Example usage:
const image = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

console.log(flipImageVertically(image));
/*
Output:
[
  [3, 2, 1],
  [6, 5, 4],
  [9, 8, 7]
]
*/

⏱️ Time and Space Complexity

πŸ”„ Alternate Approaches
| Approach | Space | Time | Notes |
| β€”β€”β€”β€”β€”β€”β€”β€”β€” | —– | β€”β€”β€”β€” | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” |
| Built-in .reverse() | O(1) | O(n) per row | Easy and expressive |
| Manual swapping with temp | O(1) | O(n) per row | Preferred for learning purpose |

✨ Bonus: Using Built-in Methods (Advanced Learners)

function flipImageBuiltIn(matrix) {
  for (let row of matrix) {
    row.reverse();
  }
  return matrix;
}

πŸ” Summary
| Concept | Details |
| ———– | —————————– |
| Goal | Flip each row in a 2D matrix |
| In-place | Yes |
| Key Pattern | Two-pointer row reversal |
| Real-world | Image processing, game boards |

| β€”β€”β€”β€”β€”- | ——————– |

| Time Complexity | O(m Γ— n) |

| Space Complexity | O(1) – in-place flip |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Delete a List’s Tail Node

Given a singly-linked list, write a method to delete its last node and return the head.

// Definition for singly-linked list node
class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

/**
 * Deletes the last node from a singly-linked list.
 * @param {ListNode} head - The head of the linked list.
 * @returns {ListNode} - The head of the updated linked list.
 */
function deleteLastNode(head) {
  // TODO: Implement deletion of last node
  return head;
}

πŸͺœ Stepper Hints
πŸ” Level 1: Discovery
1. Think about how you’d reach the end of the linked list.
2. What happens if the list only has one node?

🧩 Level 2: Getting Tactical
3. You’ll need to traverse the list using a pointer.
4. Try stopping just before the last node. That means keeping track of the second-last node.

πŸ”§ Level 3: Closer to Code
5. If current.next.next is null, you’re at the second-last node.
6. Set current.next = null to delete the last node.
7. Handle the edge case where the list has only one node β€” you’ll need to return null.

// Helper: Convert array to linked list
function arrayToList(arr) {
  if (arr.length === 0) return null;
  let head = new ListNode(arr[0]);
  let current = head;
  for (let i = 1; i < arr.length; i++) {
    current.next = new ListNode(arr[i]);
    current = current.next;
  }
  return head;
}

// Helper: Convert linked list to array for easy comparison
function listToArray(head) {
  let result = [];
  let current = head;
  while (current) {
    result.push(current.val);
    current = current.next;
  }
  return result;
}

// --- Test Cases ---
function testDeleteLastNode() {
  const testCases = [
    {
      input: [],
      expected: []
    },
    {
      input: [1],
      expected: []
    },
    {
      input: [1, 2],
      expected: [1]
    },
    {
      input: [1, 2, 3, 4],
      expected: [1, 2, 3]
    },
    {
      input: [10, 20, 30, 40, 50],
      expected: [10, 20, 30, 40]
    }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const head = arrayToList(input);
    const updatedHead = deleteLastNode(head);
    const result = listToArray(updatedHead);
    const passed = JSON.stringify(result) === JSON.stringify(expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input:    ${JSON.stringify(input)}`);
      console.log(`  Expected: ${JSON.stringify(expected)}`);
      console.log(`  Got:      ${JSON.stringify(result)}`);
    }
  });
}

// Run tests
testDeleteLastNode();

πŸ” Related LeetCode Problems
https://leetcode.com/problems/delete-node-in-a-linked-list/
https://leetcode.com/problems/remove-linked-list-elements/

A

βœ… Supporting Data Structure: ListNode Class

class ListNode {
  constructor(val = 0, next = null) {
    this.val = val;
    this.next = next;
  }
}

βœ… JavaScript Solution

/**
 * Deletes the last node of a singly-linked list.
 * @param {ListNode} head - The head of the linked list.
 * @returns {ListNode} - The updated head after deletion.
 */
function deleteLastNode(head) {
  // If the list is empty or has only one node
  if (!head || !head.next) return null;

  let current = head;

  // Traverse to the second-last node
  while (current.next && current.next.next !== null) {
    current = current.next;
  }

  // Delete the last node
  current.next = null;

  return head;
}

βœ… Example Usage

// Helper to build a list from array
function buildList(arr) {
  let dummy = new ListNode();
  let current = dummy;
  for (let val of arr) {
    current.next = new ListNode(val);
    current = current.next;
  }
  return dummy.next;
}

// Helper to print list
function printList(head) {
  const values = [];
  while (head) {
    values.push(head.val);
    head = head.next;
  }
  console.log(values.join(' β†’ '));
}

// Demo
const head = buildList([1, 2, 3, 4]);
const newHead = deleteLastNode(head);
printList(newHead); // 1 β†’ 2 β†’ 3

⏱️ Time and Space Complexity

πŸ” Alternate Approaches
| β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” | ———————————————– |
| Use a dummy node | Adds a layer of abstraction but not needed here |
| Recursive solution | Overkill and not memory efficient |
| Double traversal (count nodes) | Less efficient, not recommended |

βœ… Summary
| Concept | Value |
| β€”β€”β€”- | ——————————– |
| Goal | Remove the last node in the list |
| Technique | Traverse to second-last node |
| Edge Cases | Empty list, single-node list |
| Time/Space | O(n) / O(1) |

| β€”β€”β€”β€”β€”- | ————————————————– |

| Time Complexity | O(n) – traverse once to find the last node |

| Space Complexity | O(1) – in-place update, no extra memory |

| Approach | Notes |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Replace All Spaces

Write a method to replace all spaces in a string with a given replacement string.

/**
 * Replaces all spaces in a string with the given replacement string.
 * @param {string} str - The input string.
 * @param {string} replacement - The replacement string for spaces.
 * @returns {string} - The modified string with spaces replaced.
 */
function replaceSpaces(str, replacement) {
  // TODO: Implement space replacement logic
  return str;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1 – Open Exploration
1. How can you β€œsee” every character in the string?
2. Remember: strings in JavaScript are immutable. You can’t change them directly.
3. Think about building a new string one character at a time.

πŸ” Level 2 – Closer Direction
4. Try looping over each character of the input string.
5. When the character is a space, don’t keep it as-is.
6. Instead of adding the space, add the replacement string.

🧩 Level 3 – Specific Coding Insight
7. You can use a for loop, a for-of loop, or .split() with .map() and .join() for different styles.
8. Don’t forget to handle empty strings, no spaces, or multiple consecutive spaces.

// --- Test Cases ---
function testReplaceSpaces() {
  const testCases = [
    { input: { str: "", replacement: "-" }, expected: "" },
    { input: { str: " ", replacement: "-" }, expected: "-" },
    { input: { str: "hello world", replacement: "-" }, expected: "hello-world" },
    { input: { str: "  hello  world  ", replacement: "_" }, expected: "\_\_hello\_\_world\_\_" },
    { input: { str: "noSpacesHere", replacement: "*" }, expected: "noSpacesHere" },
    { input: { str: "a b c", replacement: "" }, expected: "abc" },
    { input: { str: "multiple    spaces", replacement: "+" }, expected: "multiple++++spaces" },
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = replaceSpaces(input.str, input.replacement);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input: str="${input.str}", replacement="${input.replacement}"`);
      console.log(`  Expected: "${expected}"`);
      console.log(`  Got:      "${result}"`);
    }
  });
}

// Run tests
testReplaceSpaces();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/replace-all-spaces/

A

βœ… JavaScript Solution

/**
 * Replaces all spaces in a string with a given replacement string.
 * @param {string} str - The original string.
 * @param {string} replacement - The string to replace spaces with.
 * @returns {string} A new string with spaces replaced.
 */
function replaceSpaces(str, replacement) {
  let result = "";

  for (const char of str) {
    if (char === " ") {
      result += replacement;
    } else {
      result += char;
    }
  }

  return result;
}

βœ… Example Usage

console.log(replaceSpaces("hello world", "%20")); // "hello%20world"
console.log(replaceSpaces("  space  here ", "_")); // "\_\_space\_\_here_"
console.log(replaceSpaces("", "-"));               // ""
console.log(replaceSpaces("nospace", "-"));        // "nospace"

⏱ Time and Space Complexity
| Space Complexity | O(n) – if using a new string (necessary in JS due to string immutability) |

πŸ” Alternate Approaches
1. Using .split() and .join() – Clean and idiomatic

function replaceSpaces(str, replacement) {
  return str.split(" ").join(replacement);
}
  1. Using .replaceAll() (ES2021+)
function replaceSpaces(str, replacement) {
  return str.replaceAll(" ", replacement);
}

βœ… Summary
| Key Point | Explanation |
| β€”β€”β€”β€”β€”β€”- | ————————————– |
| String is immutable | Build a new one, can’t modify in-place |
| Time | O(n), since you visit each char once |
| Space | O(n), for the new string |
| Built-in Tools | .split().join() or .replaceAll() |

| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |

| Time Complexity | O(n) – every character visited once |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Find the Middle of a List in a Single Pass

Given a Singly-Linked List, write a method - findMiddleNode that finds and returns the middle node of the list in a single pass.

// Definition for singly-linked list node
class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

/**
 * Finds the middle node of a singly-linked list in a single pass.
 * If there are two middle nodes, return the second one.
 * @param {ListNode} head - The head of the linked list.
 * @returns {ListNode} - The middle node.
 */
function findMiddleNode(head) {
  // TODO: Implement using fast and slow pointers
  return head;
}

πŸͺœ Stepper Hints
πŸ‘£ Stepper Hints (From Beginner to Advanced)
πŸŒ€ Level 1: Beginner Insights
1. Can you walk through the list and count how many nodes it has?
2. What if we want to find the middle without knowing the total number of nodes?

πŸ” Level 2: Hint Toward Optimization
3. Try moving two pointers through the list:
* One that moves faster than the other.
4. What happens if one pointer moves twice as fast?

🧩 Level 3: Getting to the Pattern
5. If the fast pointer reaches the end, where would the slow pointer be?
6. Can you stop when the fast pointer is null or fast.next is null?

// Helper: Convert array to linked list
function arrayToList(arr) {
  if (arr.length === 0) return null;
  let head = new ListNode(arr[0]);
  let current = head;
  for (let i = 1; i < arr.length; i++) {
    current.next = new ListNode(arr[i]);
    current = current.next;
  }
  return head;
}

// Helper: Convert linked list to array from a starting node
function listToArray(head) {
  let result = [];
  let current = head;
  while (current) {
    result.push(current.val);
    current = current.next;
  }
  return result;
}

// --- Test Cases ---
function testFindMiddleNode() {
  const testCases = [
    { input: [], expected: null },
    { input: [1], expected: 1 },
    { input: [1, 2], expected: 2 },
    { input: [1, 2, 3], expected: 2 },
    { input: [1, 2, 3, 4], expected: 3 },
    { input: [1, 2, 3, 4, 5], expected: 3 },
    { input: [10, 20, 30, 40, 50, 60], expected: 40 },
  ];

  testCases.forEach(({ input, expected }, index) => {
    const head = arrayToList(input);
    const middleNode = findMiddleNode(head);
    const passed = (middleNode && middleNode.val === expected) || (middleNode === null && expected === null);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input: ${JSON.stringify(input)}`);
      console.log(`  Expected Middle Node Value: ${expected}`);
      console.log(`  Got: ${middleNode ? middleNode.val : null}`);
    }
  });
}

// Run tests
testFindMiddleNode();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/middle-of-the-linked-list/

A

βœ… Supporting Data Structure

class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

βœ… JavaScript Solution (Two Pointer Approach)

/**
 * Finds and returns the middle node of a singly-linked list.
 * @param {ListNode} head - Head of the linked list.
 * @returns {ListNode} The middle node.
 */
function findMiddleNode(head) {
  if (!head) return null;

  let slow = head;
  let fast = head;

  // Move fast by two and slow by one
  while (fast && fast.next) {
    slow = slow.next;
    fast = fast.next.next;
  }

  // When fast reaches end, slow is at middle
  return slow;
}

βœ… Example Usage

// Helper to create a linked list from array
function buildLinkedList(arr) {
  let dummy = new ListNode();
  let current = dummy;
  for (let val of arr) {
    current.next = new ListNode(val);
    current = current.next;
  }
  return dummy.next;
}

// Test
const list = buildLinkedList([1, 2, 3, 4, 5]);
const middle = findMiddleNode(list);
console.log(middle.val); // Output: 3

⏱️ Time and Space Complexity
| Space Complexity | O(1) β€” constant space, in-place pointers |

πŸ” Alternate Approaches
1. Two-Pass Count-Based Method
First pass: count number of nodes.
Second pass: go to Math.floor(count / 2).
❌ Not optimal β€” O(2n) time.

  1. Using an Array
    Store all nodes in an array and access the middle.
    ❌ O(n) space β€” not in-place.

βœ… Summary
| Concept | Details |
| β€”β€”β€” | ————————– |
| Pattern | Two-pointer (fast & slow) |
| Time | O(n) – single traversal |
| Space | O(1) – constant space |
| Edge Case | Empty list β†’ return null |
| Preferred | Single-pass pointer method |

| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |

| Time Complexity | O(n) β€” one pass through the list |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Find the Missing Number in a Set of Numbers from 1 to 10

Given an Array containing 9 numbers ranging from 1 to 10, write a method to find the missing number. Assume you have 9 numbers between 1 to 10 and only one number is missing.

/**
 * Finds the missing number from an array of 9 numbers ranging from 1 to 10.
 * @param {number[]} arr - The array of 9 numbers.
 * @returns {number} - The missing number.
 */
function findMissingNumber(arr) {
  // TODO: Implement logic to find the missing number
  return -1;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: Open Exploration
1. Can you think of what the array should look like if no numbers were missing?
2. What does the total of numbers from 1 to 10 add up to?

πŸ” Level 2: Clue to a Strategy
3. Try adding up all the numbers in the given array.
4. Then compare that total with the expected total of numbers from 1 to 10.
5. The difference between the two will give you…?

🧩 Level 3: Getting Closer
6. Use the formula for the sum of the first n natural numbers: n * (n + 1) / 2
7. Compute 10 * 11 / 2 β€” that’s the full sum.
8. Subtract the sum of the array from this value.

// --- Test Cases ---
function testFindMissingNumber() {
  const testCases = [
    { input: [2, 3, 1, 5, 6, 7, 9, 8, 10], expected: 4 },
    { input: [1, 2, 3, 4, 5, 6, 7, 8, 9], expected: 10 },
    { input: [2, 3, 4, 5, 6, 7, 8, 9, 10], expected: 1 },
    { input: [1, 3, 4, 5, 6, 7, 8, 9, 10], expected: 2 },
    { input: [1, 2, 3, 4, 5, 7, 8, 9, 10], expected: 6 }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = findMissingNumber(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input:    [${input}]`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got:      ${result}`);
    }
  });
}

// Run tests
testFindMissingNumber();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/missing-number/

A

βœ… JavaScript Solution

/**
 * Finds the missing number in an array containing numbers 1 to 10 with one missing.
 * @param {number[]} nums - Array of 9 numbers (1 to 10, one missing).
 * @returns {number} The missing number.
 */
function findMissingNumber(nums) {
  const expectedSum = (10 * (10 + 1)) / 2; // 55
  const actualSum = nums.reduce((sum, num) => sum + num, 0);
  return expectedSum - actualSum;
}

βœ… Example Usage

console.log(findMissingNumber([1, 2, 3, 4, 5, 7, 8, 9, 10])); // Output: 6
console.log(findMissingNumber([2, 3, 4, 5, 6, 7, 8, 9, 10])); // Output: 1
console.log(findMissingNumber([1, 2, 3, 4, 5, 6, 7, 8, 9]));  // Output: 10

⏱️ Time and Space Complexity
| Space Complexity | O(1) – constant extra space |

πŸ” Alternate Approaches
| Approach | Description | Time | Space |
| β€”β€”β€”β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- | β€”β€”β€”- | —– |
| Math Sum Formula βœ… | Efficient and clean. Best for fixed range. | O(n) | O(1) |
| Sorting + Linear Scan | Sort and scan for gaps. Overkill here. | O(n log n) | O(1) |
| Set Lookup | Add 1-10 to a set, remove each in input, return remaining. | O(n) | O(n) |
| XOR Trick πŸ€“ | 1^2^3^...^10 ^ arr[0]^...^arr[8] gives missing. | O(n) | O(1) |

XOR Version (Bonus):
function findMissingNumber(nums) {
let xor = 0;

for (let i = 1; i <= 10; i++) {
xor ^= i;
}

for (let num of nums) {
xor ^= num;
}

return xor;
}

βœ… Summary
| Concept | Description |
| β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |
| Primary Trick | Use the sum of 1–10 (55) and subtract the actual sum |
| Time | O(n) |
| Space | O(1) |
| Recommended | Math sum or XOR for elegance |

| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |

| Time Complexity | O(n) – one pass through the array |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Find the First Non Duplicate Character in a String

Find the first non-duplicate character in a string. Return null if no unique character is found.

/**
 * Finds the first non-duplicate character in a string.
 * @param {string} str - The input string.
 * @returns {string|null} - The first unique character, or null if none exists.
 */
function findFirstUniqueChar(str) {
  // TODO: Implement logic to find first non-duplicate character
  return null;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: Early Thinking
1. Can you go through the string and track how often each character appears?
2. Which data structure helps you associate characters with counts?

πŸ” Level 2: Intermediate Clues
3. Try using a map or object to store how many times each character appears.
4. After you build this frequency map, go through the string again.
5. This time, look for the first character that appears only once.

🧩 Level 3: Specific Implementation Ideas
6. Watch out for case sensitivity (if β€œA” vs β€œa” matters).
7. If no such character exists, return null.

// --- Test Cases ---
function testFindFirstUniqueChar() {
  const testCases = [
    { input: "", expected: null },
    { input: "a", expected: "a" },
    { input: "aa", expected: null },
    { input: "abacabad", expected: "c" },
    { input: "aabbccdde", expected: "e" },
    { input: "aabbcc", expected: null },
    { input: "xxyz", expected: "y" },
    { input: "swiss", expected: "w" },
    { input: "teeter", expected: "r" },
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = findFirstUniqueChar(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input:    "${input}"`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got:      ${result}`);
    }
  });
}

// Run tests
testFindFirstUniqueChar();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/first-unique-character-in-a-string/

A

βœ… JavaScript Solution
~~~
/**
* Finds the first non-duplicate character in a string.
* @param {string} str - Input string to search.
* @returns {string|null} First unique character or null if none found.
*/
function firstNonDuplicateChar(str) {
const charMap = new Map();

// First pass: count character frequencies
for (const char of str) {
charMap.set(char, (charMap.get(char) || 0) + 1);
}

// Second pass: find the first character with count 1
for (const char of str) {
if (charMap.get(char) === 1) {
return char;
}
}

return null;
}
~~~

βœ… Example Usage

console.log(firstNonDuplicateChar("aabbcdd")); // "c"
console.log(firstNonDuplicateChar("aabbcc"));  // null
console.log(firstNonDuplicateChar("abcde"));   // "a"
console.log(firstNonDuplicateChar(""));        // null

⏱ Time and Space Complexity

Alternate Approach
πŸ” Alternate Approaches
1. Object instead of Map

const count = {};
for (const char of str) {
  count[char] = (count[char] || 0) + 1;
}
  1. Array for lowercase-only input
const freq = Array(26).fill(0);
for (let ch of str) freq[ch.charCodeAt(0) - 97]++;

βœ… Summary
| β€”β€”β€”β€”β€”- | ——————————– |
| Pattern | Frequency counting + linear scan |
| Time Complexity | O(n) β€” 2 linear passes |
| Space Complexity | O(1) β€” bounded by alphabet size |
| Return Type | Character or null |
| Edge Cases | Empty string, all duplicates |

| β€”β€”β€”β€”β€”- | ————————————————————————– |

| Time Complexity | O(n) – two passes over the string |

| Space Complexity | O(1) – fixed-size map (at most 26 letters if only lowercase English) |

| Feature | Notes |

Metric | Complexity |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Palindrome Tester

A palindrome is a string or sequence of characters that reads the same backward as forward. For example, β€œmadam” is a palindrome. Write a method that takes in a String and returns a boolean -> true if the input String is a palindrome and false if it is not. An empty string and a null input are considered palindromes. You also need to account for the space character. For example, β€œrace car” should return false as read backward it is β€œrac ecar”.

/**
 * Checks if the input string is a palindrome.
 * An empty string or null input is considered a palindrome.
 * Spaces are treated as-is (not ignored).
 * @param {string|null} str - The input string.
 * @returns {boolean} - True if the string is a palindrome, false otherwise.
 */
function isPalindrome(str) {
  // TODO: Implement palindrome check logic
  return false;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: High-Level Thinking
1. How would you check if the first and last characters match?
2. What about the second and second-to-last?

πŸ” Level 2: Starting the Pattern
3. Can you use two pointersβ€”one at the beginning, one at the endβ€”and move them inward?
4. What happens if they don’t match at any point?

🧩 Level 3: Edge Cases and Details
5. What should the function return for an empty string or null?
6. Should you remove spaces or punctuation? (β†’ No, compare as-is)

// --- Test Cases ---
function testIsPalindrome() {
  const testCases = [
    { input: null, expected: true },
    { input: "", expected: true },
    { input: "a", expected: true },
    { input: "aa", expected: true },
    { input: "ab", expected: false },
    { input: "madam", expected: true },
    { input: "racecar", expected: true },
    { input: "race car", expected: false },
    { input: "nurses run", expected: false },
    { input: "Was it a car or a cat I saw", expected: false }, // spaces and case matter
    { input: "step on no pets", expected: false },
    { input: "Step on no pets", expected: false }, // case sensitive
    { input: "12321", expected: true },
    { input: "123 321", expected: false },
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = isPalindrome(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? "PASSED" : "FAILED"}`);
    if (!passed) {
      console.log(`  Input:    "${input}"`);
A

βœ… JavaScript Solution

/**
 * Checks if a given string is a palindrome.
 * @param {string|null} str - The input string.
 * @returns {boolean} - True if the string is a palindrome, false otherwise.
 */
/**
 * Checks if a given string is a palindrome.
 * @param {string|null} str - The input string.
 * @returns {boolean} - True if the string is a palindrome, false otherwise.
 */
function isPalindrome(str) {
  if (str === null || str.length === 0) return true;

  let left = 0;
  let right = str.length - 1;

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

  return true;
}

βœ… Example Usage

console.log(isPalindrome("madam"));      // true
console.log(isPalindrome("racecar"));    // true
console.log(isPalindrome("race car"));   // false
console.log(isPalindrome("a"));          // true
console.log(isPalindrome(""));           // true
console.log(isPalindrome(null));         // true

⏱ Time and Space Complexity
| Time Complexity | O(n) β€” compares half of the string |
| Space Complexity | O(1) β€” no additional storage |

πŸ” Alternate Approaches
1. Reverse and Compare

function isPalindrome(str) {
  if (str === null || str.length === 0) return true;
  return str === str.split('').reverse().join('');
}

βœ… Easy to read
❌ Slightly more memory (creates new reversed string)
πŸ•’ Time: O(n), 🧠 Space: O(n)

  1. Normalize and Compare (optional case-insensitive version)
    If you want to ignore cases and punctuation:
function isStrictPalindrome(str) {
  if (str === null) return true;
  const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
  return cleaned === cleaned.split('').reverse().join('');
}

❌ Not required here (just educational)

βœ… Summary
| Concept | Value |
| β€”β€”β€”β€”β€”- | ————————————– |
| Time Complexity | O(n) |
| Space Complexity | O(1) |
| Pattern | Two-pointer or reverse-and-compare |
| Edge Cases | null, empty string β†’ true |
| Case Sensitivity | Match exactly as given (no transforms) |

| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |

Metric | Complexity |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Repeated Elements in an Array

Write a method duplicate to find the repeated or duplicate elements in an array. This method should return a list of repeated integers in a string with the elements sorted in ascending order.

/**
 * Finds duplicate elements in an array.
 * Returns a string of sorted, repeated integers.
 * @param {number[]} arr - The input array.
 * @returns {string} - Duplicates in ascending order as a string (e.g., "2,3").
 */
function duplicate(arr) {
  // TODO: Implement logic to find and return duplicates
  return "";
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: Idea Seeding
1. Can you think of a way to track how many times each number appears in the array?
2. What structure lets you associate keys with counts?

πŸ” Level 2: Narrowing Down
3. Use a map or object to keep a count of appearances.
4. Once you have counts, what defines a duplicate?

🧩 Level 3: Final Steps
5. Filter only the values that appear more than once.
6. Sort the result and convert to a comma-separated string.
7. If none, return an empty string.

// --- Test Cases ---
function testDuplicate() {
  const testCases = [
    { input: [], expected: "" },
    { input: [1], expected: "" },
    { input: [1, 2, 3], expected: "" },
    { input: [1, 2, 2, 3, 4, 4], expected: "2,4" },
    { input: [5, 3, 1, 2, 3, 5, 6, 7, 5], expected: "3,5" },
    { input: [10, 10, 10, 10], expected: "10" },
    { input: [9, 8, 7, 6, 5, 6, 7, 8, 9], expected: "6,7,8,9" },
    { input: [100, 200, 300, 100, 100, 200], expected: "100,200" }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = duplicate(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? "PASSED" : "FAILED"}`);
    if (!passed) {
      console.log(`  Input:    [${input}]`);
      console.log(`  Expected: "${expected}"`);
      console.log(`  Got:      "${result}"`);
    }
  });
}

// Run tests
testDuplicate();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/find-all-duplicates-in-an-array/

A

βœ… JavaScript Solution

/**
 * Finds and returns duplicate integers in a sorted comma-separated string.
 * @param {number[]} arr - The input array of integers.
 * @returns {string} - Comma-separated string of duplicates in ascending order.
 */
function duplicate(arr) {
  const freqMap = new Map();

  // Count each number
  for (const num of arr) {
    freqMap.set(num, (freqMap.get(num) || 0) + 1);
  }

  // Collect duplicates
  const duplicates = [];
  for (const [num, count] of freqMap.entries()) {
    if (count > 1) {
      duplicates.push(num);
    }
  }

  // Sort and convert to string
  duplicates.sort((a, b) => a - b);
  return duplicates.join(',');
}

βœ… Example Usage

console.log(duplicate([4, 3, 2, 7, 8, 2, 3, 1])); // "2,3"
console.log(duplicate([1, 2, 3, 4, 5]));          // ""
console.log(duplicate([10, 20, 10, 30, 20, 40])); // "10,20"

πŸ•“ Time and Space Complexity

🧠 Alternate Approaches
1. Using a Set for Seen & Duplicates

function duplicate(arr) {
  const seen = new Set();
  const duplicates = new Set();

  for (const num of arr) {
    if (seen.has(num)) {
      duplicates.add(num);
    } else {
      seen.add(num);
    }
  }

  return [...duplicates].sort((a, b) => a - b).join(',');
}

βœ… Cleaner in terms of logic
❌ Slightly less intuitive for beginners

βœ… Summary
| Key Concept | Value |
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |
| Pattern | Frequency map or seen-set |
| Time Complexity | O(n log n) β€” due to sort |
| Space Complexity | O(n) |
| Output Format | String of duplicates, comma-separated |
| Edge Case | No duplicates β†’ return "" |

| β€”β€”β€” | ——————————– |

| Time | O(n log n) – due to sorting step |

| Space | O(n) – for map and result array |

Operation | Complexity |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Horizontal Flip

You are given an m x n 2D image matrix where each integer represents a pixel. Flip it in-place along its horizontal axis.

/**
 * Flips the 2D matrix in-place along its horizontal axis (top-to-bottom).
 * @param {number[][]} matrix - The 2D image matrix.
 * @returns {number[][]} - The same matrix, flipped in-place.
 */
function flipHorizontal(matrix) {
  // TODO: Implement horizontal axis flip logic
  return matrix;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: Explore and Think
1. What does it mean to flip something horizontally in 2D?
2. Do you need to touch the individual columns?

πŸ” Level 2: Narrow the Focus
3. Can you swap the top row with the bottom one?
4. How many rows do you need to swap?

🧩 Level 3: Final Step
5. What happens if the matrix has an odd number of rows?
6. Try using two pointers β€” one at the top and one at the bottom β€” and move inward.

// Helper: Compare two 2D arrays for deep equality
function areMatricesEqual(m1, m2) {
  if (m1.length !== m2.length) return false;
  for (let i = 0; i < m1.length; i++) {
    if (m1[i].length !== m2[i].length) return false;
    for (let j = 0; j < m1[i].length; j++) {
      if (m1[i][j] !== m2[i][j]) return false;
    }
  }
  return true;
}

// --- Test Cases ---
function testFlipHorizontal() {
  const testCases = [
    {
      input: [],
      expected: []
    },
    {
      input: [[1]],
      expected: [[1]]
    },
    {
      input: [[1, 2], [3, 4]],
      expected: [[3, 4], [1, 2]]
    },
    {
      input: [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
      expected: [[7, 8, 9], [4, 5, 6], [1, 2, 3]]
    },
    {
      input: [[1, 0], [0, 1], [1, 1]],
      expected: [[1, 1], [0, 1], [1, 0]]
    }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const inputCopy = JSON.parse(JSON.stringify(input)); // avoid in-place mutation affecting tests
    const result = flipHorizontal(inputCopy);
    const passed = areMatricesEqual(result, expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input:`, input);
      console.log(`  Expected:`, expected);
      console.log(`  Got:`, result);
    }
  });
}

// Run tests
testFlipHorizontal();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/flipping-an-image/

A

βœ… JavaScript Solution

/**
 * Flips a 2D matrix along its horizontal axis in-place.
 * @param {number[][]} matrix - The 2D image matrix.
 * @returns {void}
 */
function flipHorizontal(matrix) {
  let top = 0;
  let bottom = matrix.length - 1;

  while (top < bottom) {
    // Swap entire rows
    [matrix[top], matrix[bottom]] = [matrix[bottom], matrix[top]];
    top++;
    bottom--;
  }
}

βœ… Example Usage

const image = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
];

flipHorizontal(image);
console.log(image);
// Output:
// [
//   [7, 8, 9],
//   [4, 5, 6],
//   [1, 2, 3]
// ]

πŸ•“ Time & Space Complexity
Metric Value
| Space Complexity | O(1) β€” in-place swap only |

🧠 Alternate Approaches
1. Using Reverse

function flipHorizontal(matrix) {
  matrix.reverse(); // Reverses rows in-place
}

βœ… Clean and uses built-in
❗ Only use if in-place mutation via .reverse() is acceptable

βœ… Summary
| Feature | Value |
| —————– | ———————————————– |
| Core Pattern | Two-pointer row swapping |
| Time Complexity | O(m Γ— n) |
| Space Complexity | O(1) in-place |
| Edge Cases | Odd number of rows β€” middle row stays untouched |
| Mutates Original? | Yes, in-place |

| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” |

| Time Complexity | O(m Γ— n) β€” touches each element once |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Unique Chars in a String

Write a method that takes in an input String and returns true if all the characters in the String are unique and false if there is even a single repeated character. The method should return true if the input is null or empty String.

/**
 * Checks if all characters in the input string are unique.
 * Returns true if input is null or empty.
 * @param {string|null} str - The input string.
 * @returns {boolean}
 */
function hasAllUniqueChars(str) {
  // TODO: Implement logic to check for unique characters
  return false;
}

πŸͺœ Stepper Hints
🌱 Level 1: Understand the Goal
1. What does β€œunique characters” mean in this context?
2. Try some example strings like β€œabc” and β€œaab” β€” what’s the expected outcome?

πŸ” Level 2: First Thoughts
3. How would you find out if a character has appeared before?
4. Can a data structure help you keep track of what you’ve seen?

🧠 Level 3: Getting Closer
5. Can you loop over the string and store each character in a Set?
6. If you encounter a character already in the Set, what does that mean?

// --- Test Cases ---
function testHasAllUniqueChars() {
  const testCases = [
    { input: null, expected: true },
    { input: "", expected: true },
    { input: "a", expected: true },
    { input: "ab", expected: true },
    { input: "abc", expected: true },
    { input: "aA", expected: true }, // case-sensitive
    { input: "aa", expected: false },
    { input: "abcdeaf", expected: false },
    { input: "1234567890", expected: true },
    { input: "112345", expected: false },
    { input: "!@#$%", expected: true },
    { input: "Hello, World!", expected: false }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = hasAllUniqueChars(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? "PASSED" : "FAILED"}`);
    if (!passed) {
      console.log(`  Input: "${input}"`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got: ${result}`);
    }
  });
}

// Run tests
testHasAllUniqueChars();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/contains-duplicate/

A

βœ… JavaScript Solution Using Set

/**
 * Checks if all characters in a string are unique.
 * @param {string|null} input
 * @returns {boolean}
 */
function hasAllUniqueCharacters(input) {
  if (input == null || input.length === 0) return true;

  const seen = new Set();

  for (const char of input) {
    if (seen.has(char)) {
      return false;
    }
    seen.add(char);
  }

  return true;
}

πŸ§ͺ Examples

console.log(hasAllUniqueCharacters("abcdef")); // true
console.log(hasAllUniqueCharacters("hello"));  // false
console.log(hasAllUniqueCharacters(""));       // true
console.log(hasAllUniqueCharacters(null));     // true

πŸ•“ Time & Space Complexity
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |
| Time Complexity | O(n) – One scan of the string |
| Space Complexity | O(n) – In worst-case, stores all unique chars in a Set |

✨ Alternate Approaches
1. Brute Force (No extra space)
Nested loops to compare every character with every other character.
Time: O(nΒ²)
Space: O(1)
βœ… Good for interviews that limit space.

  1. Using a boolean array (for ASCII-only strings)
function hasAllUniqueCharsASCII(str) {
  if (str == null || str.length === 0) return true;
  if (str.length > 128) return false; // Pigeonhole Principle

  const charSet = new Array(128).fill(false);
  for (let i = 0; i < str.length; i++) {
    const code = str.charCodeAt(i);
    if (charSet[code]) return false;
    charSet[code] = true;
  }
  return true;
}

πŸ“˜ Summary
| Approach | Time | Space | Pros | Cons |
| β€”β€”β€”β€”β€”- | —– | —– | ———————————– | ———————– |
| Hash Set | O(n) | O(n) | Simple, fast | Uses extra space |
| Brute Force | O(nΒ²) | O(1) | No extra space | Very slow for large n |
| ASCII char array | O(n) | O(1) | Fast and low memory (if ASCII only) | Not generalizable |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Binary Search on Array of Integers

Write a method that searches an Array of integers for a given integer using the Binary Search Algorithm. If the input integer is found in the array, return true. Otherwise, return false. You can assume that the given array of integers is already sorted in ascending order.

/**
 * Performs binary search on a sorted array to find a target value.
 * @param {number[]} arr - Sorted array of integers.
 * @param {number} target - Integer to search for.
 * @returns {boolean} - True if found, false otherwise.
 */
function binarySearch(arr, target) {
  // TODO: Implement binary search algorithm
  return false;
}

πŸͺœ Stepper Hints
πŸŒ€ Level 1: General Exploration
1. Do you really need to look at every element to find the target?
2. How does the fact that the array is sorted help?

πŸ”§ Level 2: Binary Logic Insight
3. What if you compare the target to the middle element?
4. Can you narrow down the range you’re searching based on that comparison?

🧩 Level 3: Closing In
5. Maintain a start and end pointer.
6. Use a while loop to keep shrinking the search window.
7. When do you stop the loop?

// --- Test Cases ---
function testBinarySearch() {
  const testCases = [
    { arr: [], target: 5, expected: false },
    { arr: [1], target: 1, expected: true },
    { arr: [1], target: 2, expected: false },
    { arr: [1, 2, 3, 4, 5], target: 1, expected: true },
    { arr: [1, 2, 3, 4, 5], target: 5, expected: true },
    { arr: [1, 2, 3, 4, 5], target: 3, expected: true },
    { arr: [1, 2, 3, 4, 5], target: 6, expected: false },
    { arr: [1, 3, 5, 7, 9, 11], target: 8, expected: false },
    { arr: [1, 3, 5, 7, 9, 11], target: 9, expected: true },
    { arr: [-10, -5, 0, 3, 8, 12], target: -5, expected: true },
    { arr: [-10, -5, 0, 3, 8, 12], target: 6, expected: false }
  ];

  testCases.forEach(({ arr, target, expected }, index) => {
    const result = binarySearch(arr, target);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Array: [${arr}]`);
      console.log(`  Target: ${target}`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got: ${result}`);
    }
  });
}

// Run tests
testBinarySearch();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/binary-search/

A

βœ… JavaScript Implementation

/**
 * Performs binary search on a sorted array.
 * @param {number[]} arr - Sorted array of integers.
 * @param {number} target - Number to search for.
 * @returns {boolean} - True if target is found, false otherwise.
 */
function binarySearch(arr, target) {
  let left = 0;
  let right = arr.length - 1;

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

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

  return false;
}

βœ… Example Usage

console.log(binarySearch([1, 3, 5, 7, 9, 11], 7)); // true
console.log(binarySearch([1, 3, 5, 7, 9, 11], 2)); // false

πŸ•“ Time and Space Complexity
| Space (Iterative) | O(1) |
| Space (Recursive) | O(log n) due to stack calls |

πŸ” Alternate Approach: Recursive Binary Search

const binarySearchRecursive = (array, target, left = 0, right = array.length - 1) => {
  if (left > right) return false;

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

  if (array[mid] === target) return true;
  if (array[mid] < target) {
    return binarySearchRecursive(array, target, mid + 1, right);
  } else {
    return binarySearchRecursive(array, target, left, mid - 1);
  }
};

βœ… Cleaner for recursion fans
❗ Stack overflow for very large arrays

πŸ” Summary
| Feature | Value |
| —————– | β€”β€”β€”β€”β€”- |
| Time Complexity | O(log n) |
| Space Complexity | O(1) (iterative) |
| Input Requirement | Sorted array |
| Output | true / false |

| —————– | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |

| Time | O(log n) β€” divide the search space by half each step |

Complexity | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Fibonacci Number

The Fibonacci Sequence is the series of numbers: 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, … The next number is found by adding up the two numbers before it. Write a recursive method fib(n) that returns the nth Fibonacci number. n is 0 indexed, which means that in the sequence 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, …, n == 0 should return 0 and n == 3 should return 2. Assume n is less than 15. Even though this problem asks you to use recursion, more efficient ways to solve it include using an Array, or better still using 3 volatile variables to keep a track of all required values.

/**
 * Recursively returns the nth Fibonacci number.
 * Assumes n < 15 and n is 0-indexed.
 * @param {number} n
 * @returns {number}
 */
function fib(n) {
  // TODO: Implement recursive Fibonacci logic
  return -1;
}

πŸͺœ Stepper Hints
🌱 Level 1: Explore the Pattern
1. Have you tried writing down the Fibonacci numbers manually?
2. Can you describe how each number is formed using the previous ones?

🧭 Level 2: Think Recursive
3. Can you define fib(n) in terms of fib(n - 1) and fib(n - 2)?
4. What’s the stopping condition? (Base cases?)

🎯 Level 3: Close to Code
5. What should fib(0) and fib(1) return?
6. Once you handle those, can your function keep calling itself until it reaches them?

// --- Test Cases ---
function testFib() {
  const testCases = [
    { input: 0, expected: 0 },
    { input: 1, expected: 1 },
    { input: 2, expected: 1 },
    { input: 3, expected: 2 },
    { input: 4, expected: 3 },
    { input: 5, expected: 5 },
    { input: 6, expected: 8 },
    { input: 7, expected: 13 },
    { input: 8, expected: 21 },
    { input: 9, expected: 34 },
    { input: 10, expected: 55 },
    { input: 11, expected: 89 },
    { input: 12, expected: 144 },
    { input: 13, expected: 233 },
    { input: 14, expected: 377 }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = fib(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? "PASSED" : "FAILED"}`);
    if (!passed) {
      console.log(`  Input: ${input}`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got: ${result}`);
    }
  });
}

// Run tests
testFib();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/fibonacci-number/

A

βœ… Recursive JavaScript Implementation

/**
 * Returns the nth Fibonacci number using recursion.
 * @param {number} n - The index of the Fibonacci number (0-indexed).
 * @returns {number}
 */
function fib(n) {
  if (n === 0) return 0;
  if (n === 1) return 1;
  return fib(n - 1) + fib(n - 2);
}

πŸ§ͺ Example Usage

console.log(fib(0)); // 0
console.log(fib(3)); // 2
console.log(fib(7)); // 13

πŸ•“ Time and Space Complexity
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |
| Time Complexity | O(2^n) – exponential due to repeated calls |
| Space Complexity | O(n) – call stack depth |

The time complexity is exponential because it makes 2 recursive calls per level.
You end up with a binary tree of calls.

πŸš€ Alternate Approaches
βœ… Iterative (Optimal for small to large n)
Store results so you don’t recalculate.

function fibIterative(n) {
  if (n === 0) return 0;
  let a = 0, b = 1;

  for (let i = 2; i <= n; i++) {
    const next = a + b;
    a = b;
    b = next;
  }

  return b;
}
  • Time: O(n)
  • Space: O(1)
  • πŸ“Œ Much faster than recursion for n > 20.

🧠 Memoized Recursive (Top-down DP)

function fibMemo(n, memo = {}) {
  if (n in memo) return memo[n];
  if (n === 0) return 0;
  if (n === 1) return 1;

  memo[n] = fibMemo(n - 1, memo) + fibMemo(n - 2, memo);
  return memo[n];
}

Time Complexity: O(n)
Space Complexity: O(n)

🧾 Summary
| Approach | Time | Space | Notes |
| β€”β€”β€”β€”β€” | β€”β€” | —– | —————————– |
| Naive Recursion | O(2^n) | O(n) | Simple, elegant, slow |
| Iterative | O(n) | O(1) | Best for performance |
| Memoized Rec | O(n) | O(n) | Combines recursion with speed |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Reverse a string

Write a method that takes in a String and returns the reversed version of the String.

/**
 * Reverses the given string.
 * @param {string|null} str - The input string.
 * @returns {string|null} - The reversed string or null if input is null.
 */
function reverseString(str) {
  // TODO: Implement logic to reverse the string
  return null;
}

πŸͺœ Stepper Hints
🌱 Level 1: Get Familiar
1. Try reading a string from the end. What happens if you print characters in reverse order?
2. What’s the difference between a character and a string?

πŸ” Level 2: Loop and Collect
3. Can you build a new string by starting from the last character?
4. Think about using a loop that counts backwards from the end.

🧠 Level 3: Built-in Helpers
5. JavaScript strings don’t have a built-in reverse()… but arrays do!
6. What happens if you convert the string into an array?

// --- Test Cases ---
function testReverseString() {
  const testCases = [
    { input: null, expected: null },
    { input: "", expected: "" },
    { input: "a", expected: "a" },
    { input: "ab", expected: "ba" },
    { input: "racecar", expected: "racecar" },
    { input: "hello", expected: "olleh" },
    { input: "JavaScript", expected: "tpircSavaJ" },
    { input: "12345", expected: "54321" },
    { input: " !@#", expected: "#@! " },
    { input: "A man, a plan, a canal", expected: "lanac a ,nalp a ,nam A" }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = reverseString(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? "PASSED" : "FAILED"}`);
    if (!passed) {
      console.log(`  Input: "${input}"`);
      console.log(`  Expected: "${expected}"`);
      console.log(`  Got: "${result}"`);
    }
  });
}

// Run tests
testReverseString();

πŸ” Related LeetCode Problem
https://leetcode.com/problems/reverse-string/

A

βœ… JavaScript Solution β€” Using Array Helpers

/**
 * Reverses the input string.
 * @param {string} str
 * @returns {string}
 */
function reverseString(str) {
  if (str == null || str.length === 0) return str;
  return str.split('').reverse().join('');
}

πŸ§ͺ Examples

console.log(reverseString("hello"));     // "olleh"
console.log(reverseString(""));          // ""
console.log(reverseString(null));        // null
console.log(reverseString("racecar"));   // "racecar"

⏱️ Time & Space Complexity
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” |
| Time Complexity | O(n) – where n is length of string |
| Space Complexity | O(n) – for intermediate array and result string |

πŸ” Alternate Approaches
1. Manual loop with a result string

function reverseStringManual(str) {
  if (str == null || str.length === 0) return str;

  let result = '';
  for (let i = str.length - 1; i >= 0; i--) {
    result += str[i];
  }
  return result;
}

Time: O(n)
Space: O(n)
πŸ”Ž Less efficient in large-scale apps due to string immutability (concatenation creates new strings each time).

  1. Using a helper function recursively (for learning)
function reverseStringRecursive(str) {
  if (str == null || str.length <= 1) return str;
  return reverseStringRecursive(str.slice(1)) + str[0];
}

Time: O(nΒ²) due to string slicing and concatenation
Space: O(n) call stack

✨ Summary Table
| Method | Time | Space | Notes |
| β€”β€”β€”β€”β€”β€”β€”β€”β€” | —– | —– | ———————————– |
| .split().reverse().join() | O(n) | O(n) | Simple and clean |
| Manual loop | O(n) | O(n) | Better for interviews (shows logic) |
| Recursion | O(nΒ²) | O(n) | Not efficient; good for learning |

Metric | Value |

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Insert a Node at the Front of a Linked List

Write a method to insert a node at the front of a singly-linked list and return the head of the modified list.

// Definition for singly-linked list node.
class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

/**
 * Inserts a new node with the given value at the front of the list.
 * @param {ListNode|null} head - The head of the current linked list.
 * @param {number} val - The value to insert.
 * @returns {ListNode} - The new head of the list.
 */
function insertAtFront(head, val) {
  // TODO: Implement logic to insert node at the front
  return null;
}

πŸͺœ Stepper Hints
🌱 Hint Level 1 β€” Understand the Structure
1. What exactly is a singly-linked list?
Can you imagine each node having a value and a pointer to the next?

πŸ› οΈ Hint Level 2 β€” Think of Insertion
2. Where does the new node need to go?
What should its .next point to?

🧠 Hint Level 3 β€” Update the Head
3. After insertion, what should now be considered the head of the list?

🎯 Hint Level 4 β€” Test the Flow
4. Try drawing the before and after picture:

Before: [1] -> [2] -> [3]
Add: 0
After:  [0] -> [1] -> [2] -> [3]
// --- Helper Functions ---
function arrayToList(arr) {
  let head = null;
  for (let i = arr.length - 1; i >= 0; i--) {
    head = new ListNode(arr[i], head);
  }
  return head;
}

function listToArray(head) {
  const result = [];
  while (head !== null) {
    result.push(head.val);
    head = head.next;
  }
  return result;
}

// --- Test Cases ---
function testInsertAtFront() {
  const testCases = [
    { head: [], val: 1, expected: [1] },
    { head: [2], val: 1, expected: [1, 2] },
    { head: [2, 3], val: 0, expected: [0, 2, 3] },
    { head: [5, 6, 7], val: 4, expected: [4, 5, 6, 7] }
  ];

  testCases.forEach(({ head, val, expected }, index) => {
    const headList = arrayToList(head);
    const newHead = insertAtFront(headList, val);
    const result = listToArray(newHead);
    const passed = JSON.stringify(result) === JSON.stringify(expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input list: [${head}], Value to insert: ${val}`);
      console.log(`  Expected: [${expected}]`);
      console.log(`  Got: [${result}]`);
    }
  });
}

// Run tests
testInsertAtFront();

πŸ” Related LeetCode Problems
https://leetcode.com/problems/reverse-linked-list/
https://leetcode.com/problems/merge-two-sorted-lists/

A

βœ… JavaScript Solution

// Define a Node structure
class ListNode {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

/**
 * Inserts a new node with the given value at the front of the list.
 * @param {ListNode|null} head - The current head of the list.
 * @param {number} value - The value for the new node.
 * @returns {ListNode} - The new head of the list.
 */
function insertAtFront(head, value) {
  const newNode = new ListNode(value);
  newNode.next = head;
  return newNode; // new node becomes the new head
}

πŸ§ͺ Example Usage

let head = new ListNode(2);
head = insertAtFront(head, 1);  // Now list is: 1 -> 2
head = insertAtFront(head, 0);  // Now list is: 0 -> 1 -> 2

⏱️ Time & Space Complexity
| Metric | Value |
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” |
| Time Complexity | O(1) – constant-time insertion |
| Space Complexity | O(1) – no extra memory (just one node) |

πŸ” Alternate Approaches
* There are no faster ways for insertion at the front. It’s already O(1) and efficient.
* If this were insertion at tail, you’d need to traverse the entire list (O(n)), unless you kept a tail pointer.

✨ Final Notes
* Inserting at the head is one of the simplest operations in a linked list.
* Always make sure the new node’s .next points to the current head.
* Then, return the new node β€” it becomes the new head.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Delete a List’s Head Node

Given a singly-linked list, write a method to delete the first node of the list and return the new head.

// Definition for singly-linked list node.
class ListNode {
  constructor(val, next = null) {
    this.val = val;
    this.next = next;
  }
}

/**
 * Deletes the first node of the list and returns the new head.
 * @param {ListNode|null} head - The head of the current linked list.
 * @returns {ListNode|null} - The new head after deletion.
 */
function deleteFirstNode(head) {
  // TODO: Implement logic to delete the first node
  return null;
}

πŸͺœ Stepper Hints
🌱 Hint 1 β€” What’s at the β€œfront”?
* What does it mean to be the β€œfirst” node of a singly-linked list?
* Which node is the β€œhead” and what comes right after it?

πŸ” Hint 2 β€” Think in Steps
* If we want to remove the first node, where should the new head point to?
* What happens to the node we skip over?

🧠 Hint 3 β€” Don’t Forget Edge Cases
* What if the list is already empty?
* What if the list has only one node?

🚦 Final Hint β€” One Pointer Away
* Just move the head pointer forward by one β€” the garbage collector will handle the rest!

// --- Helper Functions ---
function arrayToList(arr) {
  let head = null;
  for (let i = arr.length - 1; i >= 0; i--) {
    head = new ListNode(arr[i], head);
  }
  return head;
}

function listToArray(head) {
  const result = [];
  while (head !== null) {
    result.push(head.val);
    head = head.next;
  }
  return result;
}

// --- Test Cases ---
function testDeleteFirstNode() {
  const testCases = [
    { input: [], expected: [] },
    { input: [1], expected: [] },
    { input: [1, 2], expected: [2] },
    { input: [10, 20, 30], expected: [20, 30] },
    { input: [5, 6, 7, 8], expected: [6, 7, 8] }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const head = arrayToList(input);
    const newHead = deleteFirstNode(head);
    const result = listToArray(newHead);
    const passed = JSON.stringify(result) === JSON.stringify(expected);
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input: [${input}]`);
      console.log(`  Expected: [${expected}]`);
      console.log(`  Got: [${result}]`);
    }
  });
}

// Run tests
testDeleteFirstNode();

πŸ“š Related LeetCode Problems
https://leetcode.com/problems/remove-linked-list-elements/
https://leetcode.com/problems/reverse-linked-list/

A

βœ… JavaScript Solution

// Define the singly-linked list node
class ListNode {
  constructor(value) {
    this.value = value;
    this.next = null;
  }
}

/**
 * Deletes the first node of the linked list.
 * @param {ListNode|null} head - The current head of the list.
 * @returns {ListNode|null} - The new head after deletion.
 */
function deleteFirstNode(head) {
  if (!head) return null; // Edge case: list is empty
  return head.next;       // Skip the first node and return the second as the new head
}

πŸ§ͺ Example Usage

let head = new ListNode(10);
head.next = new ListNode(20);
head.next.next = new ListNode(30);

// Before: 10 -> 20 -> 30
head = deleteFirstNode(head);
// After: 20 -> 30

⏱️ Time & Space Complexity
| Metric | Value |
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€” |
| Time Complexity | O(1) – single pointer move |
| Space Complexity | O(1) – no extra space used |

πŸ› οΈ Alternate Approaches
There’s no better approach than O(1) for removing the head β€” it’s already optimal. The only alternate consideration is manual memory management, but in JavaScript, the garbage collector takes care of that.

🧠 Tips
* The beauty of linked lists is in how we manipulate pointers.
* Deleting the head just means β€œdon’t look at it anymore.”
* You don’t need to delete the node explicitly β€” just reassign the head pointer.

17
Q

Find the Number that Appears Once

Write a method that returns a number that appears only once in an array. Assume the array will surely have a unique value. The array will never be empty.

/**
 * Returns the number that appears only once in the array.
 * Assumes:
 *   - The array is non-empty.
 *   - Exactly one number appears only once.
 * @param {number[]} arr - Input array of numbers.
 * @returns {number} - The unique number.
 */
function findUniqueNumber(arr) {
  // TODO: Implement logic to find the unique number
  return -1;
}

πŸͺœ Stepper Hints
🌱 Hint 1 β€” Understand the Input
* Think about what it means for a number to appear only once.
* Try working through a sample: [4, 3, 2, 4, 2]

πŸ” Hint 2 β€” Try Brute Force First
* Can you count how many times each number appears?

🧠 Hint 3 β€” Try Using a Map or Object
* What kind of structure would help you count occurrences easily?

πŸš€ Final Hint β€” XOR Trick (Optimal Way)
* Think about how XOR (^) behaves:
* a ^ a = 0
* a ^ 0 = a
* So, num1 ^ num1 ^ num2 = num2 if num2 is the unique number.

// --- Test Cases ---
function testFindUniqueNumber() {
  const testCases = [
    { input: [1, 1, 2], expected: 2 },
    { input: [4, 3, 2, 3, 4], expected: 2 },
    { input: [10, 20, 10], expected: 20 },
    { input: [7, 7, 8, 9, 8], expected: 9 },
    { input: [99], expected: 99 },
    { input: [0, 1, 0], expected: 1 },
    { input: [5, 4, 3, 3, 4], expected: 5 }
  ];

  testCases.forEach(({ input, expected }, index) => {
    const result = findUniqueNumber(input);
    const passed = result === expected;
    console.log(`Test Case ${index + 1}: ${passed ? 'PASSED' : 'FAILED'}`);
    if (!passed) {
      console.log(`  Input: [${input}]`);
      console.log(`  Expected: ${expected}`);
      console.log(`  Got: ${result}`);
    }
  });
}

// Run tests
testFindUniqueNumber();

πŸ“š Related LeetCode Problem
https://leetcode.com/problems/single-number/

A

βœ… JavaScript Implementation
πŸ”§ Option 1: Using XOR (Optimal) β€” Recommended

/**
 * Returns the number that appears only once in the array.
 * @param {number[]} nums
 * @returns {number}
 */
function findUniqueNumber(nums) {
  let unique = 0;
  for (let num of nums) {
    unique ^= num;
  }
  return unique;
}

πŸ§ͺ Example

console.log(findUniqueNumber([2, 3, 5, 4, 5, 3, 4])); // Output: 2

⏱️ Time and Space Complexity
| Metric | Value |
| β€”β€”β€”β€”β€”- | β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”β€”- |
| Time Complexity | O(n) – One pass through the array |
| Space Complexity | O(1) – Constant extra space |

πŸ› οΈ Alternate Approaches
🧾 Option 2: Using a Hash Map

function findUniqueNumber(nums) {
  const freqMap = {};
  for (let num of nums) {
    freqMap[num] = (freqMap[num] || 0) + 1;
  }
  for (let num of nums) {
    if (freqMap[num] === 1) return num;
  }
}
  • Time Complexity: O(n)
  • Space Complexity: O(n)
    βœ… Works well but not as efficient in space as XOR.

πŸ’‘ Tip
* When you’re solving problems where values cancel each other out, consider using bitwise XOR.
* Knowing how XOR works is a useful trick in many coding interviews!