题目描述

✅ 724. 寻找数组的中心下标

image-20260928224600421

image-20260928224600423

题意分析

找到左侧元素和与右侧元素和相等的最左下标,当前元素不计入任何一边。中心下标不一定在数组中间,两端也可能满足条件;不存在元素的一侧,其和视为 0。没有合法下标时返回 -1。

解法:先算总和再左右累计

核心思路

[!blue]

对任意下标 i,数组总和可以拆成三部分:total = 左侧和 + nums[i] + 右侧和。因此只要知道总和与左侧和,就能用 total-leftSum-nums[i] 得到右侧和,不必为每个下标重新遍历两侧。

先遍历一次得到 total,再从左向右检查候选下标。每轮开始时,leftSum 恰好是 nums[0..i-1] 的和:在 i=0 时它为 0,检查结束后加上 nums[i],就成为下一轮需要的左侧和。

在这个状态下比较 leftSum == total-leftSum-nums[i],正好对应题目的左右和相等条件。检查顺序按下标递增,所以第一次相等即可返回,既不会漏掉候选,也保证结果最靠左。

解题步骤

  • 遍历数组求出 total,初始化 leftSum = 0。
  • 从下标 0 开始,比较 leftSum 与 total-leftSum-nums[i]。
  • 相等时返回 i;否则执行 leftSum += nums[i],继续检查下一项。
  • 所有下标都不满足条件时返回 -1。

只有一个元素时,两侧都为空,直接返回 0;全为 0 时,所有下标都合法,同样首先返回 0。负数不会影响总和拆分关系,仍按同一公式逐项检查。

代码实现

class Solution {
    // 直接算左右和容易重复,先求总和后按下标动态维护左侧和,右侧和可 O(1) 得出。
    public int pivotIndex(int[] nums) {
        int total = 0;

        for (int num : nums) {
            total += num;
        }

        int leftSum = 0;

        for (int i = 0; i < nums.length; i++) {
            // 比较时两侧都不含当前元素,未命中后才累加到左侧
            if (leftSum == total - leftSum - nums[i]) {
                return i;
            }

            leftSum += nums[i];
        }

        return -1;
    }
}
func pivotIndex(nums []int) int {
    // 直接算左右和容易重复,先求总和后按下标动态维护左侧和,右侧和可 O(1) 得出。
    total := 0
    for _, num := range nums {
        total += num
    }

    leftSum := 0
    for i, num := range nums {
        // 比较时两侧都不含当前元素,未命中后才累加到左侧
        if leftSum == total-leftSum-num {
            return i
        }
        leftSum += num
    }

    return -1
}

复杂度分析

  • 时间复杂度:$O(n)$,求和与检查各一次。
  • 空间复杂度:$O(1)$,两个和与游标。

关键点总结

[!green]

  • 当前元素是分割点,两侧都不包含它。
  • 含负数时不能根据和的大小决定跳过哪边。

易错点总结

[!yellow]

  • 比较之前就加入当前值,会让两侧计算错位。
  • 忽略端点,会漏掉空侧和为零的合法情况。
  • 找到后继续覆盖答案,会返回最后一个而非最左下标。

相似题目

题目 难度 关联与区别
1732. 找到最高海拔 简单 同样滚动维护前缀和,原题取累计值最大值,本题结合总和计算右侧和。
238. 除了自身以外数组的乘积 中等 同样把当前位置两侧拆成前缀与后缀,本题使用和,原题使用乘积且排除自身。
转载与许可
作者
链接 https://hgnulb.github.io/blog/2023/12581943
许可 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!