Solving tips
- Repeated range-sum queries at many positions signal prefix sums: compute total once, then each side is O(1) arithmetic.
- Sweep left to right with a running left sum; the right sum is total - left - nums[i], giving O(n) time and O(1) space.
- The pivot element belongs to neither side, so the check is left == total - left - nums[i], and edges (empty left at index 0, empty right at last) are valid.
- Compare before adding nums[i] to left, or you shift every check and miss the leftmost pivot; negatives make sums non-monotonic so no binary-search shortcut.
Problem
Given an integer array nums, find its pivot index: an index where the sum of all elements strictly to its left equals the sum of all elements strictly to its right. The element at the pivot itself belongs to neither side.
For the leftmost index, the left sum is 0; for the rightmost index, the right sum is 0. Return the leftmost pivot index, or -1 if none exists.
Examples
nums = [1,7,3,6,5,6] β 3 β left of index 3: 1 + 7 + 3 = 11; right of it: 5 + 6 = 11.
nums = [1,2,3] β -1 β no index balances (e.g. at index 0: left 0 vs right 5).
nums = [2,1,-1] β 0 β left of index 0 is empty (0), and right is 1 + (-1) = 0.
Constraints
1 <= len(nums) <= 10^4
-1000 <= nums[i] <= 1000
Recomputing both sums for every candidate index is O(n^2); the intended solution is a single O(n) pass.
Think about it first
Hint 1
For a fixed index i, what are the two sums you need? How expensive is computing them from scratch, and how many indices are there?
Hint 2
If you know the total sum of the array and the sum of everything left of i, can you get the right sum without another loop?
Hint 3
Compute `total = sum(nums)` once. Sweep i from left to right maintaining a running `left`; at each i the right sum is `total - left - nums[i]`. Return the first i where they match.
TL;DR
Running left sum against a precomputed total β O(n) time, O(1) space.
Approach 1 β Brute force
For every index, sum the elements to its left and the elements to its right with fresh loops (slices), and compare.
from typing import List
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
n = len(nums)
for i in range(n):
left = sum(nums[:i])
right = sum(nums[i + 1:])
if left == right:
return i
return -1
Complexity: O(n^2) time (each candidate re-sums nearly the whole array), O(n) space for the slices. At n = 10^4 that is ~10^8 additions β the constraints are chosen to make this time out.
Approach 2 β Prefix sum array
The insight: all those repeated sums overlap. Precompute the prefix sums β a classic technique where prefix[i] stores the sum of the first i elements β and every range sum becomes a subtraction: left of i is prefix[i], right of i is prefix[n] - prefix[i + 1].
from typing import List
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
n = len(nums)
prefix = [0] * (n + 1)
for i, x in enumerate(nums):
prefix[i + 1] = prefix[i] + x
for i in range(n):
left = prefix[i]
right = prefix[n] - prefix[i + 1]
if left == right:
return i
return -1
Walkthrough on nums = [1,7,3,6,5,6]:
prefix = [0, 1, 8, 11, 17, 22, 28].
i = 0: left 0, right 28 - 1 = 27 β no.
i = 1: left 1, right 28 - 8 = 20 β no.
i = 2: left 8, right 28 - 11 = 17 β no.
i = 3: left 11, right 28 - 17 = 11 β match, return 3.
Complexity: O(n) time, O(n) space for the prefix array.
Approach 3 β Running sum, O(1) space
The insight: you never need the whole prefix array β only the prefix at the current index. Keep one running left, and derive the right side from the fixed total: right = total - left - nums[i].
from typing import List
class Solution:
def pivotIndex(self, nums: List[int]) -> int:
total = sum(nums)
left = 0
for i, x in enumerate(nums):
if left == total - left - x:
return i
left += x
return -1
Walkthrough on nums = [2,1,-1] (total = 2):
| i | x | left | total - left - x | match? |
|---|
| 0 | 2 | 0 | 2 - 0 - 2 = 0 | yes β return 0 |
And on [1,7,3,6,5,6] (total = 28): left runs 0, 1, 8, 11; at i = 3, 28 - 11 - 6 = 11 = left β return 3.
Complexity: O(n) time, O(1) extra space.
Common pitfalls
- Including
nums[i] in one of the sides β the pivot element belongs to neither sum. The check is left == total - left - nums[i], not left == total - left.
- Updating
left += x before the comparison β that shifts every check by one element and breaks the leftmost-index guarantee.
- Forgetting the edges: index
0 (empty left side) and index n - 1 (empty right side) are legal pivots β example 3 returns 0.
- Assuming positive numbers: with negatives, sums are not monotonic, so binary-search-style shortcuts are invalid; the linear scan is the right tool.
Pattern takeaway
When a problem asks the same range-sum question at many positions, compute the total once and maintain a running prefix β every βsum of a sideβ becomes O(1) arithmetic. Prefix sums (stored or running) are the standard cure for repeated overlapping sums, and the running-variable form saves the array whenever you only consume prefixes in order.