Bird
Raised Fist0
DSA Rustprogramming~3 mins

Why Recursion on Arrays and Strings in DSA Rust?

Choose your learning style10 modes available
The Big Idea

What if you could solve big problems by solving tiny pieces again and again automatically?

The Scenario

Imagine you have a long list of numbers or a long word, and you want to find something inside it or change it step by step. Doing this by hand means checking each item one by one, which can be very slow and tiring.

The Problem

Manually going through each item in a list or each letter in a word can be confusing and easy to mess up. You might forget where you left off or make mistakes counting. It also takes a lot of time if the list or word is very long.

The Solution

Recursion lets you solve the problem by breaking it into smaller, similar problems. You tell the computer to solve a small part, then call itself to solve the next part, until it finishes. This way, the computer handles the steps automatically and correctly.

Before vs After
✗ Before
fn sum_array(arr: &[i32]) -> i32 {
    let mut total = 0;
    for i in 0..arr.len() {
        total += arr[i];
    }
    total
}
✓ After
fn sum_array(arr: &[i32]) -> i32 {
    if arr.is_empty() {
        0
    } else {
        arr[0] + sum_array(&arr[1..])
    }
}
What It Enables

Recursion on arrays and strings makes it easy to solve complex problems by breaking them into simple, repeatable steps.

Real Life Example

Think of reading a book page by page. Instead of remembering the whole book, you read one page, then ask yourself to read the next page, and so on, until you finish the book.

Key Takeaways

Manual checking of arrays or strings is slow and error-prone.

Recursion breaks problems into smaller, manageable parts.

It helps write clear and simple solutions for complex tasks.

Practice

(1/5)
1. What does recursion on arrays typically involve when processing elements?
easy
A. Using loops to iterate over the array elements
B. Calling the same function with a smaller part of the array until a base case is reached
C. Sorting the array before processing
D. Creating a new array for each element

Solution

  1. Step 1: Understand recursion on arrays

    Recursion on arrays means the function calls itself with a smaller portion of the array each time.
  2. Step 2: Identify the base case

    The recursion stops when the array is empty or has one element (base case).
  3. Final Answer:

    Calling the same function with a smaller part of the array until a base case is reached -> Option B
  4. Quick Check:

    Recursion = smaller input calls [OK]
Hint: Recursion breaks problem into smaller parts until simple case [OK]
Common Mistakes:
  • Confusing recursion with loops
  • Not defining a base case
  • Trying to process the whole array at once
2. Which of the following is the correct Rust function signature for a recursive function that takes a slice of integers?
easy
A. fn recurse(arr: &mut [i32]) -> i32
B. fn recurse(arr: Vec<i32>) -> i32
C. fn recurse(arr: i32) -> &[i32]
D. fn recurse(arr: &[i32]) -> i32

Solution

  1. Step 1: Understand Rust slice parameter

    A recursive function processing an array usually takes a slice reference like &[i32] to avoid ownership issues.
  2. Step 2: Check return type

    Returning i32 is common if the function calculates a value like sum or count.
  3. Final Answer:

    fn recurse(arr: &[i32]) -> i32 -> Option D
  4. Quick Check:

    Slice input with reference = fn recurse(arr: &[i32]) -> i32 [OK]
Hint: Use &[i32] for read-only array slices in recursion [OK]
Common Mistakes:
  • Using Vec<i32> causes ownership moves
  • Returning a reference to local data
  • Using mutable slice when not needed
3. What is the output of this Rust recursive function when called with arr = &[1, 2, 3]?
fn sum(arr: &[i32]) -> i32 {
    if arr.is_empty() {
        0
    } else {
        arr[0] + sum(&arr[1..])
    }
}

println!("{}", sum(arr));
medium
A. 0
B. 3
C. 6
D. Compilation error

Solution

  1. Step 1: Trace recursive calls

    sum(&[1,2,3]) = 1 + sum(&[2,3]) sum(&[2,3]) = 2 + sum(&[3]) sum(&[3]) = 3 + sum(&[]) sum(&[]) = 0 (base case)
  2. Step 2: Calculate total sum

    sum = 1 + 2 + 3 + 0 = 6
  3. Final Answer:

    6 -> Option C
  4. Quick Check:

    1+2+3 = 6 [OK]
Hint: Sum adds first element plus recursive sum of rest [OK]
Common Mistakes:
  • Forgetting base case returns 0
  • Adding wrong slice range
  • Confusing output with length
4. Identify the error in this recursive Rust function that tries to count occurrences of a number in an array:
fn count_occurrences(arr: &[i32], target: i32) -> i32 {
    if arr.len() == 0 {
        0
    } else if arr[0] == target {
        1 + count_occurrences(&arr[1..], target)
    } else {
        count_occurrences(arr, target)
    }
}
medium
A. Infinite recursion because the else branch calls with the same array slice
B. Missing base case for empty array
C. Incorrect comparison operator in if condition
D. Function should return bool instead of i32

Solution

  1. Step 1: Analyze recursive calls

    In the else branch, the function calls itself with the same array slice, causing infinite recursion.
  2. Step 2: Identify fix

    The else branch should call with &arr[1..] to move forward and avoid infinite loop.
  3. Final Answer:

    Infinite recursion because the else branch calls with the same array slice -> Option A
  4. Quick Check:

    Same slice call causes infinite recursion [OK]
Hint: Always reduce array size in recursive calls to avoid infinite loops [OK]
Common Mistakes:
  • Not reducing slice in else branch
  • Confusing base case condition
  • Returning wrong type
5. Given a string slice s: &str, which recursive Rust function correctly reverses the string?
hard
A. fn reverse(s: &str) -> String { if s.len() == 0 { String::new() } else { format!("{}{}", reverse(&s[1..]), &s[0..1]) } }
B. fn reverse(s: &str) -> String { if s.len() == 1 { s.to_string() } else { format!("{}{}", &s[0..1], reverse(&s[1..])) } }
C. fn reverse(s: &str) -> String { if s.is_empty() { String::new() } else { format!("{}{}", &s[0..1], reverse(&s[1..])) } }
D. } } ))]..1[s&(esrever ,]1..0[s& ,"}{}{"(!tamrof { esle } )(wen::gnirtS { )(ytpme_si.s fi { gnirtS >- )rts& :s(esrever nf

Solution

  1. Step 1: Understand string slicing and recursion

    To reverse, recursively reverse substring from index 1 onward, then append first character.
  2. Step 2: Check base case and concatenation order

    Base case is empty string returning empty String. Concatenate reversed tail + first char.
  3. Step 3: Compare options

    fn reverse(s: &str) -> String { if s.len() == 0 { String::new() } else { format!("{}{}", reverse(&s[1..]), &s[0..1]) } } matches correct base case and concatenation order.
  4. Final Answer:

    fn reverse(s: &str) -> String { if s.len() == 0 { String::new() } else { format!("{}{}", reverse(&s[1..]), &s[0..1]) } } -> Option A
  5. Quick Check:

    Reverse tail + first char = correct recursion [OK]
Hint: Reverse substring then add first char at end for string reversal [OK]
Common Mistakes:
  • Appending first char before recursive call
  • Wrong base case condition
  • Using incorrect string slices
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