Bird
Raised Fist0
DSA Goprogramming~5 mins

DP vs Recursion vs Greedy Choosing the Right Tool in DSA Go - Key Differences

Choose your learning style10 modes available
Recall & Review
beginner
What is recursion in problem solving?
Recursion is a method where a function calls itself to solve smaller parts of a problem until it reaches a simple case that can be solved directly.
Click to reveal answer
beginner
What does DP (Dynamic Programming) do differently from simple recursion?
DP stores results of solved subproblems to avoid repeating work, making the solution faster by reusing these stored answers.
Click to reveal answer
beginner
When is a greedy algorithm the right choice?
A greedy algorithm works well when choosing the best option at each step leads to the overall best solution, without needing to reconsider previous choices.
Click to reveal answer
intermediate
Why might recursion be inefficient for some problems?
Recursion can be inefficient because it may solve the same subproblems multiple times, causing extra work and slower performance.
Click to reveal answer
intermediate
How do you decide between DP and greedy approaches?
Use DP when subproblems overlap and you need to remember past results. Use greedy when local best choices lead to a global best solution without overlap.
Click to reveal answer
Which approach stores answers to subproblems to avoid repeated work?
ADynamic Programming
BGreedy Algorithm
CSimple Recursion
DBrute Force
When is a greedy algorithm most suitable?
AWhen local choices lead to global optimum
BWhen subproblems overlap
CWhen recursion depth is too large
DWhen all solutions must be checked
What is a main drawback of simple recursion without optimization?
AUses too much memory
BAlways slower than greedy
CCannot solve problems with base cases
DMay repeat solving the same subproblems
Which technique is best when subproblems do NOT overlap?
ADynamic Programming
BGreedy Algorithm
CRecursion with memoization
DBacktracking
What does memoization help with in recursion?
ASimplifies code
BMakes recursion iterative
CAvoids repeated calculations
DIncreases recursion depth
Explain how to choose between recursion, dynamic programming, and greedy algorithms for solving a problem.
Think about problem structure and if subproblems repeat or if local choices are enough.
You got /5 concepts.
    Describe a real-life example where a greedy algorithm works well and why dynamic programming would be unnecessary.
    Think about simple step-by-step choices that lead to best result.
    You got /4 concepts.

      Practice

      (1/5)
      1. Which approach is best suited when a problem has overlapping subproblems and optimal substructure?
      easy
      A. Dynamic Programming
      B. Greedy Algorithm
      C. Simple Recursion without memoization
      D. Brute Force

      Solution

      1. Step 1: Understand problem characteristics

        Overlapping subproblems means the same smaller problems repeat. Optimal substructure means the best solution can be built from best solutions of smaller parts.
      2. Step 2: Match approach to characteristics

        Dynamic Programming stores results of subproblems to avoid repeated work, ideal for overlapping subproblems and optimal substructure.
      3. Final Answer:

        Dynamic Programming -> Option A
      4. Quick Check:

        Overlapping subproblems + optimal substructure = Dynamic Programming [OK]
      Hint: Use DP when subproblems repeat and build optimal solutions [OK]
      Common Mistakes:
      • Choosing greedy when subproblems overlap
      • Using simple recursion without memoization
      • Confusing brute force with DP
      2. Which of the following Go function signatures correctly represents a recursive function to compute factorial?
      easy
      A. func factorial(n int) { if n == 0 { return 1 } return n * factorial(n-1) }
      B. func factorial(n int) int { if n == 0 { return 1 } return n * factorial(n-1) }
      C. func factorial(n int) int { if n == 0 { return 0 } return n * factorial(n-1) }
      D. func factorial(n int) int { if n == 1 { return 0 } return n * factorial(n-1) }

      Solution

      1. Step 1: Check function return type and base case

        Factorial returns int, so function must return int. Base case for factorial is n == 0 returning 1.
      2. Step 2: Verify recursive call and return statement

        Recursive call multiplies n by factorial(n-1). func factorial(n int) int { if n == 0 { return 1 } return n * factorial(n-1) } matches correct signature and logic.
      3. Final Answer:

        func factorial(n int) int { if n == 0 { return 1 } return n * factorial(n-1) } -> Option B
      4. Quick Check:

        Correct return type and base case = func factorial(n int) int { if n == 0 { return 1 } return n * factorial(n-1) } [OK]
      Hint: Check base case and return type carefully in recursion [OK]
      Common Mistakes:
      • Missing return type in function signature
      • Incorrect base case value
      • Returning wrong type or no return
      3. What is the output of this Go code using recursion to compute Fibonacci numbers?
      func fib(n int) int {
        if n <= 1 {
          return n
        }
        return fib(n-1) + fib(n-2)
      }
      
      func main() {
        fmt.Println(fib(5))
      }
      medium
      A. 3
      B. 8
      C. 5
      D. 13

      Solution

      1. Step 1: Trace fib(5) calls

        fib(5) = fib(4) + fib(3); fib(4) = fib(3) + fib(2); fib(3) = fib(2) + fib(1); fib(2) = fib(1) + fib(0)
      2. Step 2: Calculate values bottom-up

        fib(0)=0, fib(1)=1; fib(2)=1; fib(3)=2; fib(4)=3; fib(5)=5
      3. Final Answer:

        5 -> Option C
      4. Quick Check:

        Fibonacci(5) = 5 [OK]
      Hint: Remember Fibonacci sequence: 0,1,1,2,3,5,8... [OK]
      Common Mistakes:
      • Confusing index starting point
      • Miscomputing recursive calls
      • Assuming fib(1) = 0
      4. Identify the error in this greedy algorithm code snippet for coin change in Go:
      func coinChange(coins []int, amount int) int {
        count := 0
        for i := len(coins) - 1; i >= 0; i-- {
          for amount >= coins[i] {
            amount -= coins[i]
            count++
          }
        }
        if amount != 0 {
          return -1
        }
        return count
      }
      medium
      A. Greedy may fail if coins are not canonical denominations
      B. The inner loop should increment amount instead of decrement
      C. Coins array must be sorted in ascending order
      D. Return value should be amount instead of count

      Solution

      1. Step 1: Understand greedy coin change logic

        The code tries largest coins first, subtracting from amount until no longer possible.
      2. Step 2: Identify limitation of greedy approach

        Greedy works only if coin denominations are canonical (like US coins). Otherwise, it may not find minimum coins or any solution.
      3. Final Answer:

        Greedy may fail if coins are not canonical denominations -> Option A
      4. Quick Check:

        Greedy correctness depends on coin set [OK]
      Hint: Greedy coin change fails on non-standard coin sets [OK]
      Common Mistakes:
      • Assuming greedy always finds minimum coins
      • Ignoring coin order importance
      • Misunderstanding return values
      5. You want to find the longest increasing subsequence (LIS) in an array. Which approach is best and why? A) Simple recursion tries all subsequences but is slow. B) Greedy picks local best but may miss global LIS. C) Dynamic Programming stores LIS lengths to avoid recomputation. D) Brute force enumerates all subsequences without optimization.
      hard
      A. Simple recursion is best for LIS
      B. Greedy approach always finds LIS
      C. Brute force is efficient for LIS
      D. Dynamic Programming is best for LIS

      Solution

      1. Step 1: Analyze LIS problem nature

        LIS requires checking subsequences and their lengths. Simple recursion tries all but is exponential time.
      2. Step 2: Compare approaches

        Greedy fails because local choices don't guarantee global LIS. DP stores LIS lengths for subproblems, improving efficiency.
      3. Final Answer:

        Dynamic Programming is best for LIS -> Option D
      4. Quick Check:

        LIS problem = DP best approach [OK]
      Hint: Use DP for LIS to avoid exponential recursion [OK]
      Common Mistakes:
      • Choosing greedy for LIS
      • Ignoring exponential time of recursion
      • Thinking brute force is efficient
      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