Bird
Raised Fist0
Interview Prepstacks-monotonic-stackmediumAmazonBloomberg

First Unique Character in a Stream

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize frequency array and queue

Create a frequency array of size 26 initialized to zero and an empty queue to hold characters.

💡 This initialization sets up the data structures needed to track character counts and candidate unique characters.
Line:freq = [0] * 26 q = deque()
💡 The frequency array allows O(1) updates and checks for each character; the queue will maintain order of unique candidates.
📊
First Unique Character in a Stream - Watch the Algorithm Execute, Step by Step
Watching this step-by-step visualization reveals how the queue and frequency array work together to efficiently track the first unique character in a stream, which is difficult to grasp by reading code alone.
Step 1/10
·Active fill★Answer cell
no_op
Stack (top→bottom)
empty
pushElement[0]: a
Stack (top→bottom)
a
↑ pushed: a
Contributes: "a"
pushElement[1]: b
Stack (top→bottom)
b
a
↑ pushed: b
Contributes: "a"
pushElement[2]: c
Stack (top→bottom)
c
b
a
↑ pushed: c
Contributes: "a"
popElement[3]: a
Stack (top→bottom)
c
b
↓ popped: [a]
Contributes: "b"
popElement[4]: c
Stack (top→bottom)
b
↓ popped: [c]
Contributes: "b"
popElement[5]: b
Stack (top→bottom)
empty
↓ popped: [b]
Contributes: "#"
pushElement[6]: d
Stack (top→bottom)
d
↑ pushed: d
Contributes: "d"
no_opElement[6]: d
Stack (top→bottom)
d
Contributes: ["a","a","a","b","b","#","d"]
no_opElement[6]: d
Stack (top→bottom)
d
Contributes: ["a","a","a","b","b","#","d"]

Key Takeaways

✓ The queue always holds characters with frequency exactly 1, ensuring the front is the first unique character.

This property is hard to see from code alone because it requires understanding the interplay of frequency updates and queue pops.

✓ When a character repeats, it is removed from the queue, dynamically updating the first unique character without rescanning the stream.

Visualizing the queue popping repeated characters clarifies how the algorithm maintains efficiency.

✓ If the queue becomes empty, it means no unique characters remain, and the algorithm returns '#'.

This condition is subtle and critical to handle correctly, and the visualization shows exactly when and why it happens.

Practice

(1/5)
1. You are given a list of asteroids represented by integers where the absolute value represents size and the sign represents direction (positive moving right, negative moving left). When two asteroids moving in opposite directions collide, the smaller one explodes. Which algorithmic approach guarantees an optimal solution to determine the state of asteroids after all collisions?
easy
A. Sorting asteroids by size and simulating collisions from largest to smallest
B. Greedy approach that removes pairs of colliding asteroids in a single pass without revisiting previous elements
C. Dynamic programming that stores subproblems of asteroid states to avoid recomputation
D. Stack simulation that processes asteroids sequentially, resolving collisions by comparing the current asteroid with the top of the stack

Solution

  1. Step 1: Understand the collision condition

    Collisions only happen when a right-moving asteroid (positive) meets a left-moving asteroid (negative) coming after it.
  2. Step 2: Recognize stack simulation suitability

    A stack naturally models the sequence of asteroids and allows checking the last asteroid's direction and size to resolve collisions efficiently.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Stack approach handles direction and size checks correctly [OK]
Hint: Stack simulates collisions by tracking last asteroid [OK]
Common Mistakes:
  • Assuming greedy single pass without stack handles all cases
  • Using DP unnecessarily
  • Sorting breaks order-dependent collisions
2. You are given a string containing encoded patterns like 3[a2[c]], where numbers indicate how many times the substring inside brackets should be repeated. Which algorithmic approach guarantees an optimal and correct decoding of such nested patterns?
easy
A. Greedy approach that expands the first encountered bracketed substring repeatedly until no brackets remain
B. Simple recursion that decodes substrings without using any auxiliary data structures
C. Dynamic programming approach that builds solutions bottom-up using substring indices
D. Stack-based iterative approach that uses two stacks to track counts and substrings, handling nested patterns correctly

Solution

  1. Step 1: Understand nested pattern decoding

    The problem requires handling nested brackets and repeat counts, which demands tracking multiple levels of context.
  2. Step 2: Identify approach that handles nesting efficiently

    A stack-based iterative approach uses two stacks to store counts and partial decoded strings, correctly managing nested repeats without excessive recursion or incorrect greedy expansions.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Stack approach correctly decodes nested patterns like 3[a2[c]] -> accaccacc [OK]
Hint: Nested repeats require stack to track context [OK]
Common Mistakes:
  • Assuming greedy expansion works for nested patterns
  • Using recursion without proper state tracking
3. You need to implement a data structure that supports enqueue and dequeue operations using only stack operations (push and pop). Which approach guarantees an amortized O(1) time complexity per operation?
easy
A. Use two stacks: push elements onto one stack, and pop elements from the other stack, transferring elements only when the pop stack is empty.
B. Use a single stack and recursion to simulate dequeue by popping all elements and restoring them after retrieving the front.
C. Use two stacks and transfer elements from push stack to pop stack on every push operation to keep pop stack always ready.
D. Use a queue internally and simulate stacks by reversing the order on every operation.

Solution

  1. Step 1: Understand the problem constraints

    The goal is to implement a queue using stacks with efficient enqueue and dequeue operations.
  2. Step 2: Analyze approaches for efficiency

    Approach A uses two stacks and transfers elements only when the pop stack is empty, achieving amortized O(1) per operation. Approach B uses recursion and is O(n) per pop. Approach C transfers on every push, causing O(n) per push. Approach D is unrelated and inefficient.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Two stacks with lazy transfer -> amortized O(1) [OK]
Hint: Two stacks with lazy transfer gives amortized O(1) [OK]
Common Mistakes:
  • Thinking transferring on every push is optimal
  • Using recursion causing O(n) pop
4. You need to design a data structure that supports push, pop, top, and retrieving the minimum element in constant time. Which approach guarantees all operations run in O(1) time without scanning the entire stack for the minimum each time?
easy
A. Use a brute force stack and scan the entire stack to find the minimum on each getMin call.
B. Use a dynamic programming table to store minimums for all sub-stacks and update it on each push/pop.
C. Keep two stacks: one for all elements and one for minimum elements, pushing to the min stack only when a new minimum is found.
D. Maintain a single stack that stores the difference between the pushed value and the current minimum, updating the minimum accordingly.

Solution

  1. Step 1: Understand the problem constraints

    The goal is to achieve O(1) time for all operations including getMin, without scanning the entire stack.
  2. Step 2: Evaluate approaches

    Brute force scanning is O(n), dynamic programming is unnecessary and inefficient, two stacks approach works but uses extra space. The single stack with encoded differences stores relative values and updates min in O(1) time and space efficiently.
  3. Final Answer:

    Option D -> Option D
  4. Quick Check:

    Single stack encoding achieves O(1) time and O(n) space with one stack [OK]
Hint: Single stack encoding stores differences for O(1) min retrieval [OK]
Common Mistakes:
  • Thinking scanning stack for min is acceptable
  • Confusing two-stack approach as optimal space
  • Assuming DP is needed for min tracking
5. Given the following Python code for checking valid parentheses, what is the return value when the input string is "([)]"?
def isValid(s: str) -> bool:
    stack = []
    pairs = {')': '(', ']': '[', '}': '{'}
    for char in s:
        if char in pairs.values():
            stack.append(char)
        elif char in pairs:
            if not stack or stack[-1] != pairs[char]:
                return False
            stack.pop()
        else:
            return False
    return not stack
easy
A. False
B. True
C. Raises an exception
D. Depends on input length

Solution

  1. Step 1: Trace input "([)]" through the code

    Push '(' then push '['. Next char is ')', expected to match '[' but pairs[')'] = '(', top of stack is '[' -> mismatch -> return False immediately.
  2. Step 2: Confirm final output

    Function returns False as soon as mismatch is detected.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Mismatch detected at third character -> returns False [OK]
Hint: Mismatch causes immediate False return [OK]
Common Mistakes:
  • Assuming order doesn't matter and returning True incorrectly
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