题目描述
给你一个整数数组 nums ,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组的左端,那么左侧数之和视为 0 ,因为下标的左侧不存在元素。这一点对于中心下标位于数组右端的情况同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那个。如果数组不存在中心下标,返回 -1 。
核心思路:前缀和思想
这道题最直白的解法是对每个位置都重新计算左右两侧之和,但那样复杂度会达到 $O(N^2)$。利用“前缀和”的思想,我们可以将复杂度优化到 $O(N)$。
1. 数学推导
设数组总和为 totalSum,当前下标为 i,其左侧元素之和为 leftSum,当前元素值为 nums[i]。
根据题目要求,如果 i 是中心下标,则其右侧之和也必须等于 leftSum。
那么整个数组的和可以表示为:
$$totalSum = leftSum + nums[i] + rightSum$$
因为 $rightSum = leftSum$,所以:
$$totalSum = leftSum + nums[i] + leftSum$$
$$totalSum = 2 \times leftSum + nums[i]$$
结论:我们只需维护一个变量 leftSum,在遍历过程中检查 2 * leftSum + nums[i] == totalSum 是否成立即可。
代码实现 (Kotlin)
1 | class Solution { |
复杂度分析
- 时间复杂度:$O(N)$。其中 $N$ 是数组的长度。我们首先进行了一次 $O(N)$ 的求和,然后又进行了一次 $O(N)$ 的遍历。
- 空间复杂度:$O(1)$。我们只使用了常数级别的额外空间(
totalSum和leftSum变量)。
关键点总结
- 空间优化:不需要像传统的“前缀和”问题那样创建一个 $O(N)$ 长度的辅助数组,仅通过两个变量动态维护状态即可。
- 边界处理:
- 当
i = 0时,leftSum初始为0。如果0 + nums[0] + 0 == totalSum,说明第一个元素就是中心下标,逻辑完美兼容。
- 当
- 最左侧优先:通过
for循环从前向后遍历,一旦找到第一个满足条件的下标就立即返回,确保了结果是“最靠近左边”的。