前缀和题目:寻找数组的中心下标
文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:寻找数组的中心下标
出处:724. 寻找数组的中心下标
难度
3 级
题目描述
要求
给定一个整数数组 nums \texttt{nums} nums,计算数组的中心下标。
中心下标是数组的一个下标,其左侧(不包含中心下标)所有元素的和等于其右侧(不包含中心下标)所有元素的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0 \texttt{0} 0,因为在中心下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
返回最左边的中心下标。如果数组不存在中心下标,返回 -1 \texttt{-1} -1。
示例
示例 1:
输入: nums = [1,7,3,6,5,6] \texttt{nums = [1,7,3,6,5,6]} nums = [1,7,3,6,5,6]
输出: 3 \texttt{3} 3
解释:
中心下标是 3 \texttt{3} 3。
左侧数之和是 nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 \texttt{nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11} nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11。
右侧数之和是 nums[4] + nums[5] = 5 + 6 = 11 \texttt{nums[4] + nums[5] = 5 + 6 = 11} nums[4] + nums[5] = 5 + 6 = 11。
示例 2:
输入: nums = [1,2,3] \texttt{nums = [1,2,3]} nums = [1,2,3]
输出: -1 \texttt{-1} -1
解释:
数组中不存在满足条件的中心下标。
示例 3:
输入: nums = [2,1,-1] \texttt{nums = [2,1,-1]} nums = [2,1,-1]
输出: 0 \texttt{0} 0
解释:
中心下标是 0 \texttt{0} 0。
左侧数之和是 0 \texttt{0} 0(下标 0 \texttt{0} 0 左侧不存在元素)。
右侧数之和是 nums[1] + nums[2] = 1 + (-1) = 0 \texttt{nums[1] + nums[2] = 1 + (-1) = 0} nums[1] + nums[2] = 1 + (-1) = 0。
数据范围
- 1 ≤ nums.length ≤ 10 4 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{4} 1≤nums.length≤104
- -1000 ≤ nums[i] ≤ 1000 \texttt{-1000} \le \texttt{nums[i]} \le \texttt{1000} -1000≤nums[i]≤1000
解法
思路和算法
对于数组中的特定下标,该下标将数组分成三个部分:下标左侧的子数组、下标处的元素、下标右侧的子数组。左右两侧的子数组可以为空,三个部分的元素之和为整个数组的元素之和。
为了判断一个下标是否为中心下标,需要分别计算该下标左右两侧的子数组的元素之和。左侧子数组的元素之和即为数组的前缀和,将整个数组的元素之和减去左侧子数组的元素之和以及当前下标处的元素,即可得到右侧子数组的元素之和。
由于题目要求返回最左边的中心下标,因此需要首先判断下标 0 0 0 是否为中心下标。下标 0 0 0 的左侧子数组的元素之和为 0 0 0,右侧子数组的元素之和为整个数组的元素之和减去 nums [ 0 ] \textit{nums}[0] nums[0],如果下标 0 0 0 的右侧子数组的元素之和为 0 0 0,则 0 0 0 是最左边的中心下标,返回 0 0 0。
当下标 0 0 0 不是中心下标时,需要从左到右遍历数组寻找中心下标,遍历过程中更新左侧子数组的元素之和与右侧子数组的元素之和。用 leftSum \textit{leftSum} leftSum 和 rightSum \textit{rightSum} rightSum 分别表示左侧子数组的元素之和与右侧子数组的元素之和,对于 i > 0 i > 0 i>0,当遍历到下标 i i i 时,左侧子数组中增加一个元素 nums [ i − 1 ] \textit{nums}[i - 1] nums[i−1],右侧子数组中减少一个元素 nums [ i ] \textit{nums}[i] nums[i],因此将 leftSum \textit{leftSum} leftSum 的值增加 nums [ i − 1 ] \textit{nums}[i - 1] nums[i−1],将 rightSum \textit{rightSum} rightSum 的值减少 nums [ i ] \textit{nums}[i] nums[i]。更新 leftSum \textit{leftSum} leftSum 和 rightSum \textit{rightSum} rightSum 之后,如果 leftSum = rightSum \textit{leftSum} = \textit{rightSum} leftSum=rightSum,则下标 i i i 是中心下标,返回 i i i。由于是从左到右遍历数组,当第一次遇到中心下标时即返回中心下标,因此可以保证返回的中心下标一定是最左边的中心下标。
如果遍历结束之后没有找到中心下标,则数组中不存在中心下标,返回 − 1 -1 −1。
代码
class Solution {public int pivotIndex(int[] nums) {int sum = 0;for (int num : nums) {sum += num;}int length = nums.length;int leftSum = 0, rightSum = sum - nums[0];if (leftSum == rightSum) {return 0;}for (int i = 1; i < length; i++) {leftSum += nums[i - 1];rightSum -= nums[i];if (leftSum == rightSum) {return i;}}return -1;}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历数组两次,第一次计算数组所有元素之和,第二次计算数组的前缀和。
-
空间复杂度: O ( 1 ) O(1) O(1)。