DSA sheet · Arrays · Prefix sum pattern

Pivot Index

The last problem of the prefix sum pattern, and a good one to finish on because the idea is so clean. We look for the spot where the numbers on the left add up to the same total as the numbers on the right. The teacher first writes the direct solution (for every index, add up its left side and its right side with two inner loops), notes that it's O(n²) and slow, goes through the four array patterns to see which one fits, and then shows the key trick: if you know the total of the whole array and the sum on the left, the sum on the right is just total − left − the number itself. That turns the whole thing into one loop.

Every part below follows the same order:
① the question in simple words → ② what the constraints tell us → ③ intuition → ④ building the logic from examples → ⑤ approach steps → ⑥ code → ⑦ code line by line → ⑧ dry run → ⑨ complexity & remember

Part 0 · Before starting

What is a prefix sum?

A prefix is a piece of the array that starts at index 0. The prefix sum at index i is the total of nums[0] … nums[i]. Each cell is built from the one before it: prefix[i] = prefix[i-1] + nums[i]. We add one new number per cell, never the whole piece again.

index012345
nums173656
prefix18111722281 · 1+7 · 8+3 · 11+6 · 17+5 · 22+6

Why sum(l..r) = prefix[r] − prefix[l−1]

prefix[r] is the total of 0…r and prefix[l−1] is the total of 0…l−1. Subtract and the shared part disappears, leaving l…r. Example: sum(4..5) = 5 + 6 = 11 = prefix[5] − prefix[3] = 28 − 17 ✓.

The "−1 / empty prefix = 0" trick: for l = 0 there is no prefix[-1]. We treat the empty prefix (nothing taken) as 0. That is exactly what this problem's statement says too: at index 0 the left sum is 0, because nothing is on the left.

Left sum and right sum with prefix sums

For an index i, with total = sum of the whole array (= the last prefix):

nums:     1   7   3  [6]  5   6        total = 28
          \_______/       \___/
          left = 11       right = 28 - 11 - 6 = 11

The four array patterns (the teacher's checklist)

patternwhen it fits
Two pointersarray is sorted, we know which pointer to move, and only the two numbers under the pointers matter.
Sliding windowwe want a continuous subarray/substring, and every number is positive (so growing always increases the sum and shrinking always decreases it).
Prefix sumsums of pieces, often many queries, and negative numbers are fine.
Kadane's algorithmthe maximum subarray sum when numbers can be negative.

Part A · Brute force: add up both sides for every index

LeetCode 724 (the same as LeetCode 1991, Find the Middle Index)

1The question in simple words

Given an integer array nums, find the pivot index: an index where the sum of all numbers strictly to its left equals the sum of all numbers strictly to its right. The number at the pivot itself is not part of either side.

index012345
nums173656answer 3

The teacher checks two spots. At index 2 (the 3): left = 1 + 7 = 8, right = 6 + 5 + 6 = 17. Not equal → not a pivot. At index 3 (the 6): left = 1 + 7 + 3 = 11, right = 5 + 6 = 11. Equal → pivot index 3.

Two more cases from LeetCode: [1, 2, 3] → −1 (no index balances). [2, 1, -1] → 0: left of index 0 is empty (0), right is 1 + (−1) = 0.

2What the constraints tell us

3Intuition

Do exactly what the definition says. Stand on each index in turn. Add up everything on its left, add up everything on its right, compare. The first index where they match is the answer.

4Building the logic from examples

Doubt: what happens at i = 0? Do we need a special case?
→ No. The left loop runs from j = 0 while j < 0, so it runs zero times and left stays 0. That's exactly what the question asks for ("left sum at index 0 is 0"). Same at the last index: the right loop starts at n, runs zero times, right = 0.
Doubt: both sums must be reset for every i, right?
→ Yes. left = 0 and right = 0 go inside the outer loop. Otherwise the sums from the previous index would pile up.
Doubt (a small slip in the video): while explaining the left loop, the teacher says "add nums of i" into the left sum. That would add the pivot's own number again and again.
→ It should be nums[j], the number the inner pointer is on. (For the right loop she correctly uses nums[k].) The code below uses nums[j].

5Approach steps

  1. For each i from 0 to n − 1:
  2. left = 0; add nums[j] for j = 0 … i − 1.
  3. right = 0; add nums[k] for k = i + 1 … n − 1.
  4. If left == right → return i.
  5. After the loop → return −1.

6Code (Python)

Brute force (O(n²), slow)
class Solution:
    def pivotIndex(self, nums):
        n = len(nums)
        for i in range(n):
            left = 0
            for j in range(0, i):           # strictly left of i: 0 .. i-1
                left += nums[j]
            right = 0
            for k in range(i + 1, n):       # strictly right of i: i+1 .. n-1
                right += nums[k]
            if left == right:
                return i                    # first match = leftmost pivot
        return -1

7Code line by line

linewhat it means
for i in range(n):Try every index as the pivot, from left to right.
left = 0 for j in range(0, i): left += nums[j]Sum of everything before i. For i = 0 the loop is empty → 0.
right = 0 for k in range(i + 1, n): right += nums[k]Sum of everything after i. For the last index the loop is empty → 0.
if left == right: return iBalanced. Since i grows from 0, this is the leftmost such index.
return -1No index balanced the two sides.

8Dry run (hand table)

nums = [1, 7, 3, 6, 5, 6].

inums[i]left sideleftright siderightequal?
01(empty)07+3+6+5+627no
17113+6+5+620no
231+786+5+617no
361+7+3115+611yes → return 3

Notice the waste: for i = 3 we re-added 1 + 7 + 3 even though we had 1 + 7 a moment ago. Part B stops doing that.

9Complexity & remember

Remember the brute forceFor each i: left = sum of 0…i−1, right = sum of i+1…n−1, reset both every time. Equal → return i. None → −1. O(n²).

Part B · Optimal: total − left − self = right

1The question

Same question. Goal: one pass, O(n).

2Constraints → which pattern?

The teacher runs through the four patterns again, using the constraint that numbers can be negative:

3Intuition

Think of the array as three parts around index i: left | nums[i] | right. Together they make the total. So if we know the total once, and keep a running left sum as we walk, the right sum costs nothing:

The one formularight = total − left − nums[i]
  total = 28
  |<------ left = 11 ------>|<nums[3]=6>|<-- right = ? -->|
       1      7      3            6          5      6
                                  right = 28 - 11 - 6 = 11

4Building the logic from examples

Step 1: get the total once

One loop over the array: for [1, 7, 3, 6, 5, 6], total = 28. (In Python just sum(nums); the teacher writes a for-each loop that adds every number.)

Step 2: walk with a running left sum

Start left = 0: when standing on index 0, nothing is on the left. Then at each index:

  1. Compute right = total − left − nums[i]. We subtract nums[i] because the current number belongs to neither side.
  2. If left == right → return i.
  3. Otherwise add nums[i] to left, because when we step to i + 1, the number we're standing on now becomes part of its left side.
Doubt: why do we update left after the check and not before?
→ At index i, left must hold only numbers strictly before i. If we added nums[i] first, left would include the pivot's own number, and the comparison would be wrong. Example: at i = 3, adding 6 first gives left = 17, right = 28 − 17 − 6 = 5, and we would miss the real pivot. So: check first, then add, ready for the next index.
Doubt: where's the "prefix sum" here? There's no prefix array.
→ left is the prefix sum, kept in one variable instead of a whole array: at index i it equals prefix[i−1]. We only ever need the latest value, so one variable is enough. A version with a full prefix array is shown below too, so you can see it's the same idea.

5Approach steps

  1. total = sum of all numbers.
  2. left = 0.
  3. For each i: right = total - left - nums[i].
  4. If left == right → return i.
  5. left += nums[i].
  6. After the loop → return −1.

6Code (Python)

Optimal: running left sum (the teacher's solution)
class Solution:
    def pivotIndex(self, nums):
        total = 0
        for num in nums:                    # total of the whole array
            total += num

        left = 0                            # nothing on the left of index 0
        for i in range(len(nums)):
            right = total - left - nums[i]  # everything after i
            if left == right:
                return i                    # leftmost pivot
            left += nums[i]                 # nums[i] joins the left side for i+1
        return -1
Same idea, written with a prefix array (for comparison)
class Solution:
    def pivotIndex(self, nums):
        n = len(nums)
        prefix = [0] * (n + 1)              # prefix[i] = sum of nums[0..i-1]; prefix[0] = 0 (empty)
        for i in range(n):
            prefix[i + 1] = prefix[i] + nums[i]
        total = prefix[n]
        for i in range(n):
            left = prefix[i]                # sum of 0 .. i-1
            right = total - prefix[i + 1]   # sum of i+1 .. n-1
            if left == right:
                return i
        return -1

The second version shifts the prefix array by one cell so that prefix[0] = 0 is the empty prefix. It uses O(n) extra space for no gain, which is why the teacher keeps just a variable.

7Code line by line

linewhat it means
for num in nums: total += numAdd up the whole array once (same as sum(nums)).
left = 0Running sum of everything before the current index. Empty at the start.
for i in range(len(nums)):Stand on each index once, left to right.
right = total - left - nums[i]Whatever isn't on the left and isn't me must be on the right. O(1).
if left == right: return iBalanced. Going left to right guarantees the leftmost pivot.
left += nums[i]Move nums[i] into the left side before stepping to i + 1.
return -1No pivot exists.

8Dry run (hand table)

nums = [1, 7, 3, 6, 5, 6], total = 28.

inums[i]left (before check)right = 28 − left − nums[i]left == right?left after the step
01028 − 0 − 1 = 27no1
17128 − 1 − 7 = 20no8
23828 − 8 − 3 = 17no11
361128 − 11 − 6 = 11yes → return 3—

Same rows as the brute force table, but each right sum came from one subtraction instead of a loop.

index012345
nums173656
left018111722grey = never reached
right2720171160

A case with a negative number: [2, 1, -1], total = 2. i = 0: left 0, right = 2 − 0 − 2 = 0 → equal → return 0. Negatives cause no trouble.

No pivot: [1, 2, 3], total = 6. i = 0: right 5 vs left 0. i = 1: left 1, right 3. i = 2: left 3, right 0. Never equal → −1.

9Complexity & remember

Remember Pivot Indextotal once. Walk with left = 0: right = total − left − nums[i]; equal → return i; then left += nums[i]. End → −1.
The teacher's study tipDon't copy-paste the solution. Once you understand it, close it and write it again from a blank editor. If you can do that, you've really learned it.

Part C · Revision page

Brute forceRunning left sum
left suminner loop 0…i−1 every timeone variable, grows by nums[i] each step
right suminner loop i+1…n−1 every timetotal − left − nums[i]
leftmost pivotscan left → right, return first matchsame
timeO(n²) ≈ 10⁸, very slowO(n) ✓
spaceO(1)O(1)
patternfits here?why
Two pointersnonot sorted; we need whole sums
Sliding windownoneeds all numbers positive, here they can be negative
Kadane'snofinds a maximum sum, not a balance point
Prefix sumyessums of sides, negatives are fine
If you remember only 5 lines 1. Pivot: sum strictly left == sum strictly right; the pivot's own number is on neither side.
2. Edges: the left sum at index 0 is 0; the right sum at the last index is 0.
3. left + nums[i] + right = total → right = total − left − nums[i].
4. Check first, then left += nums[i].
5. First match is the leftmost; none → −1. O(n) time, O(1) space.
Mistakes to avoid ✗ including nums[i] in the left or right sum
✗ adding nums[i] to left before the comparison
✗ adding nums[i] instead of nums[j] inside the brute-force left loop
✗ not resetting left/right for each i in the brute force
✗ skipping index 0 or the last index (they can be pivots)
✗ returning the last match instead of the first
test it yourself (paste under any solution)
s = Solution()
print(s.pivotIndex([1, 7, 3, 6, 5, 6]))   # 3
print(s.pivotIndex([1, 2, 3]))            # -1
print(s.pivotIndex([2, 1, -1]))           # 0
print(s.pivotIndex([5]))                  # 0  (both sides empty)
print(s.pivotIndex([0, 0, 0]))            # 0  (leftmost)
print(s.pivotIndex([-1, -1, 0, 1, 1, 0])) # 5

Based on this video: Find Pivot Index | Prefix Sum pattern