Bird
Raised Fist0
DSA Typescriptprogramming~5 mins

Why Backtracking and What Greedy Cannot Solve in DSA Typescript - Quick Recap

Choose your learning style10 modes available
Recall & Review
beginner
What is the main idea behind backtracking?
Backtracking tries all possible options step-by-step and goes back (undoes) when a choice leads to a dead end, helping find all or the best solutions.
Click to reveal answer
beginner
Why can't greedy algorithms solve all problems?
Greedy algorithms make the best local choice at each step but may miss the best overall solution because they don't reconsider earlier choices.
Click to reveal answer
intermediate
Give an example problem where greedy fails but backtracking works.
The "Subset Sum" problem: Greedy might pick large numbers first and miss a valid subset, but backtracking tries all combinations to find the correct subset.
Click to reveal answer
intermediate
How does backtracking explore the solution space?
Backtracking explores by building solutions incrementally and abandoning paths that cannot lead to a valid solution, effectively pruning the search space.
Click to reveal answer
intermediate
What is a key sign that a problem might need backtracking instead of greedy?
If the problem requires checking many combinations or the best global solution depends on future choices, greedy likely fails and backtracking is needed.
Click to reveal answer
Which approach tries all possible solutions and backtracks when stuck?
ABacktracking
BGreedy
CDivide and Conquer
DDynamic Programming
Why might a greedy algorithm fail to find the best solution?
AIt uses recursion.
BIt tries all combinations.
CIt only looks at local best choices, not the whole problem.
DIt sorts the input first.
Which problem is a classic example where greedy fails but backtracking works?
ABinary Search
BSubset Sum
CMerge Sort
DBreadth-First Search
What does backtracking do when it finds a dead end?
AIt goes back and tries a different path.
BIt stops immediately.
CIt picks the next best local choice.
DIt sorts the data.
Which is a sign that backtracking might be needed?
AThe problem is linear.
BThe problem is sorted.
CThe problem has only one solution.
DThe problem needs checking many combinations.
Explain why greedy algorithms can fail and how backtracking solves those cases.
Think about local vs global decisions and exploring all possibilities.
You got /4 concepts.
    Describe a real-life example where backtracking is better than greedy.
    Imagine picking items to fit a bag exactly.
    You got /4 concepts.

      Practice

      (1/5)
      1. Why is backtracking preferred over greedy algorithms for solving problems like the N-Queens puzzle?
      easy
      A. Because greedy algorithms always find the optimal solution faster
      B. Because backtracking explores all possible solutions and can undo choices, while greedy makes irreversible choices
      C. Because backtracking uses less memory than greedy algorithms
      D. Because greedy algorithms are only used for sorting problems

      Solution

      1. Step 1: Understand backtracking's approach

        Backtracking tries all possible options and can go back (undo) if a choice leads to failure.
      2. Step 2: Compare with greedy approach

        Greedy algorithms make the best immediate choice but cannot undo it, so they may miss the correct solution.
      3. Final Answer:

        Because backtracking explores all possible solutions and can undo choices, while greedy makes irreversible choices -> Option B
      4. Quick Check:

        Backtracking = explores all + undo [OK]
      Hint: Backtracking tries all paths; greedy picks one path only [OK]
      Common Mistakes:
      • Thinking greedy always finds the best solution
      • Confusing backtracking with brute force
      • Believing backtracking uses less memory
      2. Which of the following TypeScript code snippets correctly represents the start of a backtracking function signature?
      easy
      A. function backtrack(path number[], options number[]): void
      B. function backtrack(path: number[], options: number[]) => void
      C. function backtrack(path: number[], options: number[]): void
      D. function backtrack(path: number[], options: number[]): number

      Solution

      1. Step 1: Check TypeScript function syntax

        Correct syntax uses colon ':' to specify types and parentheses for parameters.
      2. Step 2: Verify return type and arrow usage

        function backtrack(path: number[], options: number[]): void uses correct syntax with void return type; others have syntax errors or wrong return type.
      3. Final Answer:

        function backtrack(path: number[], options: number[]): void -> Option C
      4. Quick Check:

        Correct TypeScript function syntax = function backtrack(path: number[], options: number[]): void [OK]
      Hint: Look for colons and parentheses in function parameters [OK]
      Common Mistakes:
      • Missing colons between parameter and type
      • Using arrow '=>' incorrectly in function signature
      • Wrong return type specified
      3. Consider this TypeScript backtracking code snippet for generating subsets:
      function backtrack(start: number, path: number[], nums: number[], result: number[][]) {
        result.push([...path]);
        for (let i = start; i < nums.length; i++) {
          path.push(nums[i]);
          backtrack(i + 1, path, nums, result);
          path.pop();
        }
      }
      
      const nums = [1, 2];
      const result: number[][] = [];
      backtrack(0, [], nums, result);
      console.log(result);
      What is the output printed?
      medium
      A. [[], [2], [1, 2], [1]]
      B. [[1], [2]]
      C. [[1, 2]]
      D. [[], [1], [1, 2], [2]]

      Solution

      1. Step 1: Trace backtracking calls with nums = [1, 2]

        Start with empty path [], add it to result. Then add 1, recurse, add [1], add 2, recurse, add [1,2], backtrack, add 2 alone, add [2].
      2. Step 2: Collect all subsets generated

        Subsets are [], [1], [1, 2], and [2] in order.
      3. Final Answer:

        [[], [1], [1, 2], [2]] -> Option D
      4. Quick Check:

        All subsets generated = [[], [1], [1, 2], [2]] [OK]
      Hint: Backtracking with push/pop generates all subsets including empty [OK]
      Common Mistakes:
      • Forgetting to add empty subset
      • Not popping after recursion causing wrong subsets
      • Mixing order of subsets
      4. The following TypeScript backtracking code tries to find all permutations of [1, 2], but it has a bug:
      function permute(nums: number[], path: number[], used: boolean[], result: number[][]) {
        if (path.length === nums.length) {
          result.push(path);
          return;
        }
        for (let i = 0; i < nums.length; i++) {
          if (used[i]) continue;
          path.push(nums[i]);
          used[i] = true;
          permute(nums, path, used, result);
          path.pop();
          used[i] = false;
        }
      }
      
      const result: number[][] = [];
      permute([1, 2], [], [false, false], result);
      console.log(result);
      What is the bug and how to fix it?
      medium
      A. Bug: Pushing path directly causes reference issues; fix by pushing a copy of path
      B. Bug: used array is not updated correctly; fix by removing used[i] = false
      C. Bug: Base case condition is wrong; fix by changing path.length === nums.length to path.length > nums.length
      D. Bug: Loop should start from 1 instead of 0; fix by changing for loop start

      Solution

      1. Step 1: Identify the problem with pushing path

        Pushing path directly adds the same array reference multiple times, causing all entries to be the same final path.
      2. Step 2: Fix by pushing a copy of path

        Use result.push([...path]) to push a new array copy each time.
      3. Final Answer:

        Bug: Pushing path directly causes reference issues; fix by pushing a copy of path -> Option A
      4. Quick Check:

        Push copy of path, not reference [OK]
      Hint: Always push a copy of path in backtracking results [OK]
      Common Mistakes:
      • Pushing path reference instead of copy
      • Incorrect base case condition
      • Misusing used array updates
      5. You want to solve the classic "Subset Sum" problem: given an array of positive integers and a target sum, find if any subset sums exactly to the target. Why can't a greedy algorithm solve this correctly in all cases, and how does backtracking help?
      hard
      A. Greedy fails because picking largest numbers first may miss exact sum; backtracking tries all subsets to find exact match
      B. Greedy fails because it sorts the array; backtracking sorts and tries subsets
      C. Greedy fails because it uses recursion; backtracking uses iteration
      D. Greedy fails because it only works on sorted arrays; backtracking only works on unsorted arrays

      Solution

      1. Step 1: Understand greedy approach limitation

        Greedy picks the largest numbers first, which may overshoot or miss the exact target sum.
      2. Step 2: How backtracking solves the problem

        Backtracking tries all subsets by including or excluding each number, ensuring it finds an exact sum if it exists.
      3. Final Answer:

        Greedy fails because picking largest numbers first may miss exact sum; backtracking tries all subsets to find exact match -> Option A
      4. Quick Check:

        Subset sum needs all subsets tried = Greedy fails because picking largest numbers first may miss exact sum; backtracking tries all subsets to find exact match [OK]
      Hint: Subset sum needs all subsets; greedy picks only some [OK]
      Common Mistakes:
      • Thinking greedy always finds exact sum
      • Confusing sorting with solving approach
      • Believing backtracking is iterative only
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard