Bird
Raised Fist0
Interview Prepchallenge-problemshardAmazonGoogleFacebookMicrosoftBloomberg

Trapping Rain Water

Choose your preparation mode4 modes available
▶
Steps
setup

Initialize pointers and variables

Set left pointer at index 0 and right pointer at index 11 (end of array). Initialize left_max, right_max, and water to 0.

💡 Starting pointers at both ends allows scanning inward to find trapped water efficiently.
Line:left, right = 0, len(height) - 1 left_max, right_max = 0, 0 water = 0
💡 We prepare to compare heights from both ends to decide which pointer to move.
📊
Trapping Rain Water - Watch the Algorithm Execute, Step by Step
Watching the pointers move and how trapped water accumulates visually reveals the logic behind the two-pointer approach, making the algorithm intuitive without needing to parse code alone.
Step 1/11
·Active fill★Answer cell
setup
left
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
compare
left
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
shrink
left
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
move_left
0
0
left
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
compare
0
0
left
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
shrink
0
0
left
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
2
10
right
1
11
Result: 0
move_right
0
0
left
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
right
2
10
1
11
Result: 0
record
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
left
1
9
right
2
10
1
11
Result: 6
compare
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
left
1
9
right
2
10
1
11
Result: 6
move_left
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
right
2
10
1
11
Result: 6
reconstruct
0
0
1
1
0
2
2
3
1
4
0
5
1
6
3
7
2
8
1
9
right
2
10
1
11
Result: 6

Key Takeaways

✓ The two-pointer approach efficiently calculates trapped water by moving inward from both ends and using max boundaries.

This insight is hard to see from code alone because it requires understanding why the smaller height pointer moves and how max boundaries limit trapped water.

✓ Trapped water at each position depends on the difference between the current height and the max height seen so far on that side.

Visualizing the max heights and pointer movements clarifies how water accumulates only where bars are lower than these boundaries.

✓ Pointer movement decisions are based on comparing heights at pointers, ensuring the algorithm processes the limiting side first.

The trace shows concrete examples of when and why the left or right pointer moves, which is subtle in code but clear visually.

Practice

(1/5)
1. You are given an integer array and a target value. The task is to count the number of triplets in the array such that the sum of the triplet is less than the target. Which approach guarantees an optimal solution in terms of time complexity?
easy
A. Use three nested loops to check all triplets and count those with sum less than target.
B. Sort the array, then for each element use two pointers to find pairs that form triplets with sum less than target.
C. Use dynamic programming to store counts of sums and build up to triplets.
D. Use a greedy approach by always picking the smallest elements first to form triplets.

Solution

  1. Step 1: Understand problem constraints

    The problem requires counting triplets with sum less than a target, which suggests checking combinations efficiently.
  2. Step 2: Identify approach that reduces complexity

    Sorting and using two pointers allows scanning pairs efficiently for each fixed element, reducing complexity from O(n^3) to O(n^2).
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Sorting + two pointers is a classic pattern for 3Sum variants [OK]
Hint: Sorting + two pointers reduces triple loops to quadratic [OK]
Common Mistakes:
  • Assuming brute force is optimal
  • Thinking DP applies directly here
  • Believing greedy always works for sum constraints
2. Consider the following code snippet for removing duplicates from a sorted array:
def remove_duplicates(nums):
    if len(nums) == 0:
        return 0
    uniqueIndex = 0
    for currentIndex in range(1, len(nums)):
        if nums[currentIndex] != nums[uniqueIndex]:
            uniqueIndex += 1
            nums[uniqueIndex] = nums[currentIndex]
    return uniqueIndex + 1

arr = [1,1,2]
length = remove_duplicates(arr)
print(length)
What is the output of the print statement?
easy
A. 2
B. 3
C. 1
D. 0

Solution

  1. Step 1: Trace uniqueIndex and currentIndex

    Start uniqueIndex=0, currentIndex=1: nums[1]=1 equals nums[0]=1, no increment. currentIndex=2: nums[2]=2 != nums[0]=1, increment uniqueIndex to 1, set nums[1]=2.
  2. Step 2: Return value

    uniqueIndex is 1, so return 1+1=2, indicating two unique elements.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Output matches expected unique count for input [1,1,2] [OK]
Hint: Unique count equals last uniqueIndex + 1 [OK]
Common Mistakes:
  • Returning uniqueIndex instead of uniqueIndex + 1
  • Off-by-one errors in loop
3. What is the time complexity of the optimal 3Sum Closest algorithm that sorts the array and uses two pointers to find the closest sum?
medium
A. O(n³) because it checks all triplets
B. O(n²) because it fixes one element and uses two pointers for the other two
C. O(n log n) due to sorting and linear scan
D. O(n² log n) because sorting and binary searching pairs

Solution

  1. Step 1: Identify sorting cost

    Sorting takes O(n log n) time.
  2. Step 2: Analyze nested loops

    Outer loop runs O(n) times; inner two-pointer scan runs O(n) total per outer iteration -> O(n²).
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Sorting + two-pointer scanning yields O(n²) total [OK]
Hint: Two pointers inside one loop -> O(n²) time [OK]
Common Mistakes:
  • Confusing brute force O(n³) with optimal
  • Ignoring sorting cost
  • Assuming binary search inside loop
4. The following code attempts to move zeroes to the end of the array in-place:
def moveZeroes(nums):
    lastNonZeroFoundAt = 0
    for num in nums:
        if num != 0:
            nums[lastNonZeroFoundAt] = num
            lastNonZeroFoundAt += 1
    # Bug introduced here
    for i in range(lastNonZeroFoundAt, len(nums)):
        nums[i] = nums[i]
What is the bug in this code?
medium
A. The variable lastNonZeroFoundAt is incremented incorrectly.
B. The first loop does not correctly identify non-zero elements.
C. The second loop does not fill zeroes after lastNonZeroFoundAt, leaving old values intact.
D. The assignment inside the first loop overwrites zeroes incorrectly.

Solution

  1. Step 1: Analyze second loop behavior

    The second loop assigns nums[i] = nums[i], which does nothing and fails to fill zeroes.
  2. Step 2: Identify correct fix

    It should assign nums[i] = 0 to move zeroes to the end properly.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Zeroes remain unfilled, causing incorrect output [OK]
Hint: Second loop must fill zeroes, not copy existing values [OK]
Common Mistakes:
  • Forgetting to fill zeroes after moving non-zero elements
  • Misunderstanding loop purpose
5. If the problem changes so that the same element can be used multiple times to reach the target sum (i.e., elements can be reused), which approach correctly solves the problem?
hard
A. Use the two pointers approach moving inward, but allow pointers to stay if sum < target to reuse elements.
B. Use a modified binary search that allows searching from the current index (not i+1) to reuse elements.
C. Use a dynamic programming approach to find combinations allowing repeated elements.
D. Use the brute force nested loops but break early when sum exceeds target.

Solution

  1. Step 1: Understand reuse requirement

    Allowing reuse means pairs can include the same element multiple times, which breaks two-pointer and binary search assumptions.
  2. Step 2: Identify suitable approach

    Dynamic programming can handle combinations with repeated elements efficiently, unlike two pointers or binary search.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    DP handles repeated elements and target sums correctly [OK]
Hint: Reuse -> DP for combinations, not two pointers or binary search [OK]
Common Mistakes:
  • Trying to reuse pointers incorrectly
  • Modifying binary search without correctness
  • Assuming 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