寻找数组的中心下标 图解题解
这道题到底在问什么
- 输入
- nums = [1,7,3,6,5,6]
- 输出
- 3(下标 3 左边 1+7+3=11,右边 5+6=11,相等)
最优解:一步一步想明白
- 3两个关键量:total 是固定的总和,leftSum 是边走边攒的左边和。右边和 = total − leftSum − 当前值,一减就有,省去重复累加。
- 4第一步:先把整个数组加一遍,得到总和 total = 7。后面每个位置的右边和都靠它减出来,不用再重复加。
- 5leftSum 记「当前位置左边的和」,一开始是 0(下标 0 左边什么都没有)。指针 i 从最左边开始检查。
- 6指针 i 到下标 0(高亮的是它左边那段)。左边和是 0;右边和不用重加,用 total 7 减去左边和 0 再减去自己 3,得 4。
- 7左边和 0 和右边和 4 不相等,下标 0 不是中心下标(标红)。把当前值 3 累加进 leftSum,再去看下一个位置。
- 8指针 i 到下标 1(高亮的是它左边那段)。左边和是 3;右边和不用重加,用 total 7 减去左边和 3 再减去自己 -2,得 6。
- 9左边和 3 和右边和 6 不相等,下标 1 不是中心下标(标红)。把当前值 -2 累加进 leftSum,再去看下一个位置。
- 10指针 i 到下标 2(高亮的是它左边那段)。左边和是 1;右边和不用重加,用 total 7 减去左边和 1 再减去自己 1,得 5。
- 11左边和 1 和右边和 5 不相等,下标 2 不是中心下标(标红)。把当前值 1 累加进 leftSum,再去看下一个位置。
- 12指针 i 到下标 3(高亮的是它左边那段)。左边和是 2;右边和不用重加,用 total 7 减去左边和 2 再减去自己 -4,得 9。
- 13左边和 2 和右边和 9 不相等,下标 3 不是中心下标(标红)。把当前值 -4 累加进 leftSum,再去看下一个位置。
- 14指针 i 到下标 4(高亮的是它左边那段)。左边和是 -2;右边和不用重加,用 total 7 减去左边和 -2 再减去自己 2,得 7。
- 15左边和 -2 和右边和 7 不相等,下标 4 不是中心下标(标红)。把当前值 2 累加进 leftSum,再去看下一个位置。
- 16指针 i 到下标 5(高亮的是它左边那段)。左边和是 0;右边和不用重加,用 total 7 减去左边和 0 再减去自己 -1,得 8。
- 17左边和 0 和右边和 8 不相等,下标 5 不是中心下标(标红)。把当前值 -1 累加进 leftSum,再去看下一个位置。
- 18指针 i 到下标 6(高亮的是它左边那段)。左边和是 -1;右边和不用重加,用 total 7 减去左边和 -1 再减去自己 2,得 6。
- 19左边和 -1 和右边和 6 不相等,下标 6 不是中心下标(标红)。把当前值 2 累加进 leftSum,再去看下一个位置。
- 20指针 i 到下标 7(高亮的是它左边那段)。左边和是 1;右边和不用重加,用 total 7 减去左边和 1 再减去自己 -3,得 9。
- 21左边和 1 和右边和 9 不相等,下标 7 不是中心下标(标红)。把当前值 -3 累加进 leftSum,再去看下一个位置。
- 22指针 i 到下标 8(高亮的是它左边那段)。左边和是 -2;右边和不用重加,用 total 7 减去左边和 -2 再减去自己 2,得 7。
- 23左边和 -2 和右边和 7 不相等,下标 8 不是中心下标(标红)。把当前值 2 累加进 leftSum,再去看下一个位置。
- 24指针 i 到下标 9(高亮的是它左边那段)。左边和是 0;右边和不用重加,用 total 7 减去左边和 0 再减去自己 7,得 0。
- 25左边和 0 正好等于右边和 0!下标 9(高亮这一格)就是中心下标。题目要最靠左的,找到第一个就可以直接返回 9。
⚠️ 容易写错的地方
✗ 错:右边和也用循环重新累加
✓ 对:右边和 = total − left − nums[i],一步算出
重新累加让每个位置都是 O(n),整体退化成 O(n²);用总和减是 O(1)
✗ 错:把中心下标自己算进左边或右边
✓ 对:判断时左右两边都要排除 nums[i] 本身
中心下标本身不参与比较,所以右边和要减掉一个 nums[i]
✗ 错:判断相等后忘了 return、或先加 left 再判断
✓ 对:先判断再把当前值并入 left
顺序错会让 left 提前包含当前值,判断的就不是「严格左边」了;找到也要立即返回最靠左的
完整代码(Python / C++ / Java)
Python
def pivotIndex(nums):
total = sum(nums) # 数组总和
left = 0 # 当前位置左边的和
for i, x in enumerate(nums):
if left == total - left - x: # 左和 == 右和
return i
left += x # 把当前值并入左边
return -1C++
int pivotIndex(vector<int>& nums){
int total = 0;
for (int x : nums) total += x;
int left = 0;
for (int i = 0; i < nums.size(); i++) {
if (left == total - left - nums[i]) return i;
left += nums[i];
}
return -1;
}Java
public int pivotIndex(int[] nums) {
int total = 0;
for (int x : nums) total += x;
int left = 0;
for (int i = 0; i < nums.length; i++) {
if (left == total - left - nums[i]) return i;
left += nums[i];
}
return -1;
}复杂度
时间
O(n)
求总和扫一遍,再走一遍逐位判断,每位只做常数次加减比较
空间
O(1)
只用 total 和 left 两个变量,不开额外数组
看不够?换成动画再走一遍
上面的推演每一步都对应一帧动画。点开交互动画版,能一步步看着 寻找数组的中心下标 的数据怎么变、指针怎么走,还能切 Python / Java / C++ 跟着练。
面试官可能追问
为什么求一次总和就能避免重复累加右边?+
因为右边和 = 总和 − 左边和 − 当前值。总和是固定的,左边和边走边维护,所以右边和每步只用一次减法就拿到,不必再循环加一遍。
如果有多个中心下标怎么办?+
题目要求返回最靠左的。从左往右扫,遇到第一个满足条件的下标就立即返回,自然就是最左的那个。
下标 0 或最后一个下标能当中心下标吗?+
能。下标 0 左边为空、左边和算作 0;最后一个下标右边为空、右边和算作 0。只要另一边的和也是 0 就成立。
想听吴师兄把这道题讲给你听?
文字版和动画都随便看。开通图解算法年卡,可以听吴师兄把 寻找数组的中心下标 一步步讲透(全站已上线 905 份讲透,持续扩充), 卡住的地方还有 AI 私教小欧就着动画帮你拆到懂。
把这道题真正拿下
本平台为独立第三方培训机构,与华为技术有限公司无任何关联;课程的服务内容与权益以购买协议为准,学习效果因个人情况而异。「华为 OD」「华为可信」等仅为对岗位与考试方向的客观描述,相关商标归各自权利人所有。