Cosmic Module
D
Qubits of DPK
March 15, 2026
Core DSA
1️⃣ LC #303 — Range Sum Query Immutable
Core Idea
Precompute prefix sums. Any range sum [l,r] = prefix[r+1] - prefix[l] in O(1).
Brute Force → O(n) per query | O(1) Space:
Scan from l to r each query.
Optimized → O(n) build | O(1) per query | O(n) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [-2, 0, 3, -5, 2, -1]
Prefix array build:
prefix = [0, -2, -2, 1, -4, -2, -3]
Queries:
- sumRange(0,2) = prefix[3] - prefix[0] = 1 - 0 = 1
- sumRange(2,5) = prefix[6] - prefix[2] = -3 - (-2) = -1
Key Tricks
- prefix[0] = 0 — represents empty prefix (crucial)
- Size is n+1 not n
- Query formula: prefix[right+1] - prefix[left]
30-Second Interview Explanation
Build prefix array of size n+1 where prefix[i] = sum of nums[0..i-1]. Range sum [l,r] = prefix[r+1] - prefix[l]. O(n) build, O(1) per query.
️ Interview Traps
- Off-by-one: prefix[right+1] - prefix[left] not prefix[right] - prefix[left-1]
- prefix[0] = 0 not prefix[0] = nums[0]
Most Common Follow-ups
Q1: LC #304 — 2D Range Sum (matrix)?
Extend to 2D: prefix[i][j] = sum of rectangle from (0,0) to (i-1,j-1). Query: prefix[r2+1][c2+1] - prefix[r1][c2+1] - prefix[r2+1][c1] + prefix[r1][c1] (inclusion-exclusion). Build O(mn), query O(1).
Q2: What if array is mutable (updates allowed)?
Use Binary Indexed Tree (Fenwick Tree) or Segment Tree. Both give O(log n) update and O(log n) query instead of O(n) rebuild. This is LC #307 — Range Sum Query Mutable.
2️⃣ LC #2574 — Left and Right Sum Differences
Core Idea
For each index, compute sum of all elements to its left and right. Use prefix and suffix arrays.
Optimized → O(n) Time | O(n) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [10, 4, 8, 3]
Output: [15, 1, 11, 22]
Key Tricks
- leftSum[0] = 0, rightSum[n-1] = 0 — boundary elements have no left/right
- Build left left-to-right, right right-to-left
30-Second Interview Explanation
Build prefix (left sums) and suffix (right sums) in two passes. Result[i] = abs(leftSum[i] - rightSum[i]). Time O(n), Space O(n).
️ Interview Traps
- Including current element in left or right sum — they're excluded by definition
Most Common Follow-ups
Q1: Can you do it in O(1) extra space?
Yes — compute total sum first. Then single pass: leftSum starts at 0, rightSum = total - leftSum - nums[i]. Same as Pivot Index (LC #724) approach.
3️⃣ LC #1732 — Find the Highest Altitude
Core Idea
Running prefix sum of gain array gives altitude at each point. Find maximum.
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: gain = [-5, 1, 5, 0, -7]
Output: 1
Key Tricks
- Start altitude = 0 (starting point), maxAltitude = 0 (starting point is valid)
- Running sum of gain = altitude at each biker point
30-Second Interview Explanation
Running prefix sum of gain array = altitude at each point. Track max. Initialize both to 0 since starting altitude is 0. Time O(n), Space O(1).
️ Interview Traps
- Initializing maxAltitude to gain[0] instead of 0 — starting point (altitude 0) might be the max
Most Common Follow-ups
Q1: Return the index of highest altitude?
Track maxIndex alongside maxAltitude. Update when new max found.
4️⃣ LC #1991 — Find the Middle Index
Core Idea
Identical to LC #724 Pivot Index. rightSum = totalSum - leftSum - nums[i].
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [2, 3, -1, 8, 4], totalSum = 16
Output: 3
Key Tricks
- rightSum = totalSum - leftSum - nums[i]
- Update leftSum AFTER the check
- Identical logic to LC #724
30-Second Interview Explanation
rightSum = totalSum - leftSum - current. Single pass. Time O(n), Space O(1).
️ Interview Traps
- Updating leftSum before check — includes current element
Most Common Follow-ups
Q1: This is identical to LC #724 — what's the difference?
Exactly the same problem. LC #1991 asks for leftSum == rightSum (not including pivot), LC #724 asks for the same. They're functionally identical — same code solves both.
5️⃣ LC #1310 — XOR Queries of a Subarray
Core Idea
Prefix XOR. XOR of range [l, r] = prefix[r+1] XOR prefix[l].
Optimized → O(n + q) Time | O(n) Space:
java
QUBITS OF DPK
Dry Run
Input: arr = [1,3,4,8], queries = [[0,1],[1,2],[0,3],[3,3]]
Prefix XOR:
prefix = [0, 1, 2, 6, 14]
Queries:
- [0,1]: prefix[2]^prefix[0] = 2^0 = 2
- [1,2]: prefix[3]^prefix[1] = 6^1 = 7
- [0,3]: prefix[4]^prefix[0] = 14^0 = 14
- [3,3]: prefix[4]^prefix[3] = 14^6 = 8
Key Tricks
- Same structure as prefix sum but with XOR operator
- prefix[r+1] ^ prefix[l] gives XOR of range [l,r]
- Works because XOR is self-inverse: a ^ a = 0
30-Second Interview Explanation
Prefix XOR array. Range XOR [l,r] = prefix[r+1] XOR prefix[l]. Build O(n), each query O(1). Time O(n+q), Space O(n).
️ Interview Traps
- Using prefix[r] ^ prefix[l-1] — off by one without the +1 shift
Most Common Follow-ups
Q1: Why does XOR prefix work like sum prefix?
XOR is associative, commutative, and self-inverse (a^a=0). Just like subtraction cancels sum, XOR-ing the same prefix twice cancels it. prefix[r+1] ^ prefix[l] = XOR of elements from l to r because the [0,l-1] portion cancels out.
6️⃣ LC #238 — Product of Array Except Self
Core Idea
result[i] = prefix product left of i × suffix product right of i. Store prefix in result, multiply suffix on the fly.
(This problem appears in Pattern 1 Hard — see that solution page for full details)
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [1,2,3,4]
Left pass: [1,1,2,6]
Right pass (suffix=1): index 3→2→1→0 gives [24,12,8,6]
Output: [24,12,8,6]
Key Tricks
- Left pass fills prefix, right pass multiplies suffix in-place
- No division allowed — and breaks for zeros
30-Second Interview Explanation
Each answer = left prefix × right suffix. First pass stores prefix. Second pass multiplies suffix on the fly. No division. Time O(n), Space O(1).
️ Interview Traps
- Division approach breaks for zeros
Most Common Follow-ups
Q1: What if array has zeros?
Prefx/suffix approach handles naturally — zero contributes 0 to products where it appears, correctly making all products 0 for those positions.
7️⃣ LC #977 — Squares of a Sorted Array
Core Idea
Negatives and positives both increase when squared moving away from zero. Two pointers from both ends, fill result from largest to smallest.
Brute Force → O(n log n): Square all, sort.
Optimized → O(n) Time | O(n) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [-4,-1,0,3,10]
Output: [0,1,9,16,100]
Key Tricks
- Fill result from back — largest squares go first
- Largest square is always at one of the two ends
- Two pointers inward, result pointer backward
30-Second Interview Explanation
Largest squares at both ends. Two pointers from ends, fill result array from back. Larger square goes to current back index. Time O(n), Space O(n).
️ Interview Traps
- Trying to fill from front — you'd need to shift elements
- Not handling all-negative or all-positive arrays (works correctly either way)
Most Common Follow-ups
Q1: Can you do it in-place O(1) extra space?
No clean O(n) in-place solution. The O(n) two-pointer approach requires the output array. Best in-place is O(n log n) sort after squaring.
8️⃣ LC #1413 — Minimum Value to Get Positive Step by Step Sum
Core Idea
Find minimum prefix sum. Answer = max(1, 1 - minPrefixSum) so running total never drops below 1.
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [-3,2,-3,4,2]
Answer = max(1, 1-(-4)) = max(1, 5) = 5
Key Tricks
- Need: startValue + minPrefixSum >= 1 → startValue >= 1 - minPrefixSum
- Math.max(1, ...) ensures minimum answer is 1 even if all sums are positive
30-Second Interview Explanation
Find minimum prefix sum across array. Answer = max(1, 1 - minPrefixSum). This ensures startValue + every prefix sum >= 1. Time O(n), Space O(1).
️ Interview Traps
- Forgetting Math.max(1, ...) — if all elements positive, answer must still be at least 1
Most Common Follow-ups
Q1: What if we need total >= k instead of >= 1?
Change formula to Math.max(1, k - minPrefixSum). Same logic, just different target threshold.
9️⃣ LC #1893 — Check if All 1's Are at Least Length K Places Apart
Core Idea
Track last seen position of 1. If gap between consecutive 1s is less than k, return false.
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [1,0,0,0,1,0,0,1], k=2
Output: true
Key Tricks
- i - lastOne - 1 = number of zeros between the two 1s
- lastOne = -1 means no 1 seen yet — skip check
30-Second Interview Explanation
Track last 1's position. For each new 1, compute gap = i - lastOne - 1 (zeros between them). If gap < k, return false. Time O(n), Space O(1).
️ Interview Traps
- Using i - lastOne instead of i - lastOne - 1 — that counts 1s themselves, not zeros between
Most Common Follow-ups
Q1: What if we want at least k 1s between any two 0s?
Same approach — swap roles of 0 and 1 in the code.
LC #724 — Find Pivot Index
(Core solution in Pattern 1 Easy — see that page)
Optimized → O(n) Time | O(1) Space:
java
QUBITS OF DPK
Dry Run
Input: nums = [1,7,3,6,5,6], total=28
Output: 3
Key Tricks
- rightSum = total - leftSum - nums[i] (derived, not computed)
- Update leftSum AFTER check
30-Second Interview Explanation
rightSum = totalSum - leftSum - current. Derive rightSum on the fly. Time O(n), Space O(1).
️ Interview Traps
- Updating leftSum before check includes current element incorrectly
Most Common Follow-ups
Q1: LC #1991 is identical — same code?
Yes — same problem different name. Same code submits on both.
Q2: Return all pivot indices?
Don't return early — collect all matching indices in ArrayList.