Bird
Raised Fist0
DSA Rustprogramming~20 mins

Dynamic Stack Using Resizable Array in DSA Rust - Practice Problems & Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Dynamic Stack Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Output of Push and Pop Operations on Dynamic Stack
What is the printed state of the stack after the following operations?

Push 10, Push 20, Pop, Push 30, Push 40, Pop
DSA Rust
struct Stack {
    data: Vec<i32>,
}

impl Stack {
    fn new() -> Self {
        Stack { data: Vec::new() }
    }

    fn push(&mut self, val: i32) {
        self.data.push(val);
    }

    fn pop(&mut self) -> Option<i32> {
        self.data.pop()
    }

    fn print(&self) {
        for val in self.data.iter() {
            print!("{} -> ", val);
        }
        println!("null");
    }
}

fn main() {
    let mut stack = Stack::new();
    stack.push(10);
    stack.push(20);
    stack.pop();
    stack.push(30);
    stack.push(40);
    stack.pop();
    stack.print();
}
A10 -> 30 -> null
B10 -> 20 -> 30 -> null
C10 -> 30 -> 40 -> null
D30 -> 40 -> null
Attempts:
2 left
💡 Hint
Remember that pop removes the last pushed element.
🧠 Conceptual
intermediate
1:30remaining
Capacity Growth in Dynamic Stack
If a dynamic stack implemented with a resizable array doubles its capacity when full, what is the capacity after pushing 9 elements starting from an initial capacity of 4?
A16
B12
C8
D4
Attempts:
2 left
💡 Hint
Capacity doubles only when full.
🔧 Debug
advanced
2:00remaining
Identify the Bug in Pop Method
What error occurs when running this pop method if the stack is empty?

fn pop(&mut self) -> i32 { self.data.pop().unwrap() }
DSA Rust
struct Stack {
    data: Vec<i32>,
}

impl Stack {
    fn pop(&mut self) -> i32 {
        self.data.pop().unwrap()
    }
}

fn main() {
    let mut stack = Stack { data: Vec::new() };
    stack.pop();
}
AReturns None
BReturns 0 silently
Cpanic at 'called `Option::unwrap()` on a `None` value'
DCompilation error due to missing return type
Attempts:
2 left
💡 Hint
What happens when unwrap is called on None?
📝 Syntax
advanced
1:30remaining
Correct Syntax for Push Method
Which option correctly implements the push method for the dynamic stack?
DSA Rust
struct Stack {
    data: Vec<i32>,
}

impl Stack {
    fn push(&mut self, val: i32) {
        // fill here
    }
}
Aself.data.add(val);
Bdata.push(val);
Cself.push(val);
Dself.data.push(val);
Attempts:
2 left
💡 Hint
Vec uses push method to add elements.
🚀 Application
expert
3:00remaining
Final Stack State After Mixed Operations
Given a dynamic stack starting empty, what is the final printed stack after these operations?

Push 5, Push 10, Push 15, Pop, Push 20, Pop, Pop, Push 25, Push 30
DSA Rust
struct Stack {
    data: Vec<i32>,
}

impl Stack {
    fn new() -> Self {
        Stack { data: Vec::new() }
    }

    fn push(&mut self, val: i32) {
        self.data.push(val);
    }

    fn pop(&mut self) -> Option<i32> {
        self.data.pop()
    }

    fn print(&self) {
        for val in self.data.iter() {
            print!("{} -> ", val);
        }
        println!("null");
    }
}

fn main() {
    let mut stack = Stack::new();
    stack.push(5);
    stack.push(10);
    stack.push(15);
    stack.pop();
    stack.push(20);
    stack.pop();
    stack.pop();
    stack.push(25);
    stack.push(30);
    stack.print();
}
A10 -> 20 -> 25 -> 30 -> null
B5 -> 25 -> 30 -> null
C5 -> 10 -> 25 -> 30 -> null
D25 -> 30 -> null
Attempts:
2 left
💡 Hint
Track each push and pop carefully in order.

Practice

(1/5)
1. What is the main advantage of using a dynamic stack implemented with a resizable array compared to a fixed-size array stack?
easy
A. It does not require resizing or copying elements.
B. It can grow or shrink in size as needed during runtime.
C. It always has a fixed maximum size.
D. It uses less memory than a linked list stack.

Solution

  1. Step 1: Understand fixed vs dynamic size

    A fixed-size array stack has a set capacity that cannot change during runtime, limiting the number of elements it can hold.
  2. Step 2: Analyze dynamic stack behavior

    A dynamic stack using a resizable array can increase or decrease its capacity by resizing the underlying array, allowing it to handle more or fewer elements as needed.
  3. Final Answer:

    It can grow or shrink in size as needed during runtime. -> Option B
  4. Quick Check:

    Dynamic resizing = flexible size [OK]
Hint: Dynamic stack resizes array to fit elements [OK]
Common Mistakes:
  • Thinking dynamic stack has fixed size
  • Confusing linked list with array stack
  • Assuming no resizing needed
2. Which Rust code snippet correctly doubles the capacity of a vector when the stack is full?
easy
A. if stack.len() == stack.capacity() { stack.reserve(stack.capacity()); }
B. if stack.len() == stack.capacity() { stack.reserve(1); }
C. if stack.len() == stack.capacity() { stack.reserve(stack.len() / 2); }
D. if stack.len() == stack.capacity() { stack.reserve(0); }

Solution

  1. Step 1: Understand vector capacity and reserve method

    The vector's capacity is the total space allocated. To double capacity, we add capacity() more space using reserve(capacity()).
  2. Step 2: Check each option's reserve argument

    if stack.len() == stack.capacity() { stack.reserve(stack.capacity()); } reserves current capacity again, doubling it. Others reserve too little or zero, not doubling.
  3. Final Answer:

    if stack.len() == stack.capacity() { stack.reserve(stack.capacity()); } -> Option A
  4. Quick Check:

    Reserve current capacity to double [OK]
Hint: Reserve current capacity to double vector size [OK]
Common Mistakes:
  • Reserving fixed small number instead of doubling
  • Using zero in reserve causing no growth
  • Confusing len() with capacity()
3. What will be the output of the following Rust code implementing a dynamic stack?
struct Stack {
    data: Vec<i32>,
}

impl Stack {
    fn new() -> Self {
        Stack { data: Vec::new() }
    }
    fn push(&mut self, val: i32) {
        self.data.push(val);
    }
    fn pop(&mut self) -> Option<i32> {
        self.data.pop()
    }
    fn print(&self) {
        for v in self.data.iter().rev() {
            print!("{} -> ", v);
        }
        println!("null");
    }
}

fn main() {
    let mut stack = Stack::new();
    stack.push(10);
    stack.push(20);
    stack.pop();
    stack.push(30);
    stack.print();
}
medium
A. 20 -> 10 -> null
B. 30 -> 20 -> null
C. 10 -> 30 -> null
D. 30 -> 10 -> null

Solution

  1. Step 1: Trace push and pop operations

    Push 10: stack = [10]; Push 20: stack = [10, 20]; Pop: removes 20, stack = [10]; Push 30: stack = [10, 30]
  2. Step 2: Understand print order

    Print iterates in reverse order: top is last element pushed, so prints 30 then 10, then null.
  3. Final Answer:

    30 -> 10 -> null -> Option D
  4. Quick Check:

    Stack top to bottom = 30, 10 [OK]
Hint: Pop removes last pushed; print reverses vector [OK]
Common Mistakes:
  • Forgetting pop removes last element
  • Printing in wrong order (not reversed)
  • Confusing push order with print order
4. Identify the bug in this Rust code snippet for a dynamic stack push method:
fn push(&mut self, val: i32) {
    if self.data.len() == self.data.capacity() {
        self.data.reserve(self.data.len());
    }
    self.data.push(val);
}
medium
A. reserve argument should be capacity(), not len()
B. reserve should be called after push, not before
C. No bug; code works correctly
D. push should be called only if capacity is not full

Solution

  1. Step 1: Check the resizing logic

    When self.data.len() == self.data.capacity(), the stack is full. reserve(self.data.len()) requests additional space for len() more elements. Since len() == capacity() at this point, it doubles the capacity.
  2. Step 2: Verify correctness

    reserve(self.data.capacity()) would be equivalent here. The code safely resizes before push, preventing issues, and works correctly. (Rust Vec::push auto-resizes too, but manual is valid.)
  3. Final Answer:

    No bug; code works correctly -> Option C
  4. Quick Check:

    len() == capacity() when called, so doubles [OK]
Hint: When full, reserve(len()) == reserve(capacity()), doubles size [OK]
Common Mistakes:
  • Reserving too little space (e.g., reserve(1))
  • Calling reserve after push causing potential panic
  • Assuming push auto-resizes without manual check
5. You want to implement a dynamic stack in Rust that shrinks its capacity when the number of elements falls below one-quarter of the capacity to save memory. Which approach correctly achieves this behavior?
hard
A. After pop, if len() < capacity() / 4, call data.shrink_to(len())
B. After pop, if len() < capacity() / 2, call data.reserve(len())
C. After pop, if len() < capacity() / 4, call data.reserve(capacity() / 2)
D. After pop, if len() < capacity() / 4, do nothing; shrinking is automatic

Solution

  1. Step 1: Understand shrinking condition

    We want to shrink when elements are less than 25% of capacity to save memory.
  2. Step 2: Use shrink_to method correctly

    Calling shrink_to(len()) reduces capacity to fit current elements, freeing unused space.
  3. Step 3: Analyze options

    After pop, if len() < capacity() / 4, call data.shrink_to(len()) correctly checks condition and calls shrink_to(len()). Others either use wrong methods or do nothing.
  4. Final Answer:

    After pop, if len() < capacity() / 4, call data.shrink_to(len()) -> Option A
  5. Quick Check:

    Shrink when quarter full using shrink_to(len()) [OK]
Hint: Shrink vector capacity with shrink_to(len()) when quarter full [OK]
Common Mistakes:
  • Using reserve instead of shrink_to for shrinking
  • Shrinking at half capacity instead of quarter
  • Assuming automatic shrinking without code
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