当前:LC724 · 寻找数组的中心下标 · 首次出现于 Day 46 · 路径:顶栏「56天打卡」→ 点击 LC 题号 → 逐题动画

LC724 · Find Pivot Index · 前缀和

中心下标:左边和等于总和减左减自己

先加出总和。走到每个位置,左边已经累过的数是 left,右边不用再加:总和减去 left 再减去自己。两边相等就停。

一趟求出 total。再从左到右维护 left。若 left == total − left − nums[i],i 就是中心下标;否则 left 加上 nums[i] 继续。找不到返回 -1。时间 O(n),空间 O(1)。

时间 O(n)空间 O(1)结论先行 · 全文约 6 节
导读

给你一个整数数组,找一个中心下标:它左边所有数的和,等于它右边所有数的和。中心自己不计入任何一边。左边或右边可以是空的,空的和按 0 算。有多个就返回最左边那个;没有就返回 -1。

主例 nums = [1, 7, 3, 6, 5, 6]。下标 3 上是 6,左边 1+7+3=11,右边 5+6=11,两边相等,答案是 3。

每个位置都把左右两段重新加一遍能做对,但是平方级。本文要回答:为什么右侧和不必另存数组,以及主例从下标 0 走到 3 时,left 和 right 分别是哪些数。

右侧和不用另算,用总和减

第一直觉是对每个下标 i,把左边 0..i-1 加一遍,右边 i+1..n-1 加一遍。主例 6 个数,大约再加几十次。结果能对,但左边那截每次只多一个数,却被从头重加。另一种错觉是先做完整前缀和数组再减:能把每次查询变成常数,可是多占了一整份数组,而本题每个下标只问一次、还是从左往右问。

缺的是一个随扫描更新的左侧和。先把整个数组加起来得到 total,主例 1+7+3+6+5+6=28。走到 i 时,left 表示严格在 i 左边的和;那么 i 右边的和一定是 total 减去 left 再减去 nums[i]——三部分拼起来就是全集,没有第四块。比较 left 和这个差,相等就返回 i。不相等,把 nums[i] 累进 left,继续往右。

为什么空间是常数:left 一个变量就够,不必留下每一格的前缀。为什么必须先算 total:没有全集,就无法用减法得到右侧。为什么先比较再累加:比较时 nums[i] 还不能进 left,它不属于任何一边;判定失败之后才把它交给未来的左侧。

用手走主例。i=0,左边空,left=0,right=28-0-1=27,不等,left 变成 1。i=1,left=1,right=28-1-7=20,不等,left 变成 8。演示下一帧跳到 i=2:left=1+7=8,right=28-8-3=17,仍不等,left 变成 11。

i=3 时 left=11,right=28-11-6=11,相等,返回 3。后面的 5、6 不用看,题目要最左边的中心。

下标 0 也可能是答案:左边和是 0,只要右边总和等于 0。全数组只有一个数时,左右都空,0=0,答案是 0。找不到时 left 会一路累完,返回 -1。不要把中心自己加进某一边,主例若把 6 算进左边会得到 17 对 11,错过唯一解。

为什么 O(1) 空间每个下标只检查一次,而且按从左到右的顺序检查。左侧和现场累加即可,右侧和由 total − left − 自己还原。前缀和数组能做,但本题用不上随机访问。
nums=[1,7,3,6,5,6], total=28
1pivot0
71
32
63
54
65
total=28left=0right=27不相等
i=0: left=0, right=27,不等

Go:单次扫描

solution.goGo
func pivotIndex(nums []int) int {
total := 0
for _, x := range nums { total += x }
left := 0
for i, x := range nums {
if left == total-left-x { return i }
left += x
}
return -1
}

1第一趟只求 total。主例 28。不要在第二趟里再改 total。

2先比较、后累加。比较时 x 是中心,不在 left 里。主例 i=3 时 left 仍是 11,28-11-6=11。

3从左往右第一处命中就是最左中心。扫完没有命中返回 -1。

总结

左边累加值对上「总和减左减自己」,就是中心。主例下标 3,11 对 11。

  • 中心自己不计入任何一边。先比后加,顺序反了会错过主例。
  • 右侧和不必另存。主例 i=0、2、3 的 right 分别是 27、17、11。
  • 空侧和为 0。找不到返回 -1。额外只要两个整数变量。
同族题目
LC560和为 K 的子数组LC1480一维数组的动态和LC238除自身以外数组的乘积