文章目录
- 🍓1. 题目
- 🫒2. 算法原理
- 🦄解法一:暴力枚举
- 🦄解法二:前缀和
- 🥔3. 代码实现
🍓1. 题目
题目链接:724. 寻找数组的中心下标 - 力扣(LeetCode)
给你一个整数数组 nums
,请计算数组的 中心下标 。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果中心下标位于数组最左端,那么左侧数之和视为 0
,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。
如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1
。
示例 1:
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
示例 2:
输入:nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心下标。
示例 3:
输入:nums = [2, 1, -1]
输出:0
解释:
中心下标是 0 。
左侧数之和 sum = 0 ,(下标 0 左侧不存在元素),
右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0 。
提示:
1 <= nums.length <= 104
-1000 <= nums[i] <= 1000
🫒2. 算法原理
🦄解法一:暴力枚举
这题的意思就是找到一个所谓的“中间位置”(不包含这个位置),让其两边的和都相等,如果整个数组都找完了,没有符合的,那么久返回-1
,这题定位在简单级别,直接想法就是暴力枚举。
遍历数组,每个中心下标都枚举出左边和右边的元素和,这个时间复杂度为O(N2),这里就不作示例了。
🦄解法二:前缀和
我们可以用前缀和的思想来优化这个暴力解法
不要笨重的记
dp[i] = dp[i-1] + arr[i]
模板,根据题目实际需求分析
这里要求一个下标的左边和右边的元素,我们可以采用f
表示前缀和数组,g
表示后缀和数组:
f[i]
表示[0,i-1]
区间所有元素的和
f[i] = f[i-1] + nums[i-1]
g[i]
表示[i+1,n-1]
区间所有元素的和
g[i] = g[i+1] + nums[i+1]
有了前缀和与后缀和数组,我们直接判断f[i] == g[i]
即可
细节问题:
- 初始化:这里是从下标
0
开始的,那么f[0]
就需要特殊处理一下,f[0] = 0
;
同理g[n-1]
也是,g[n-1] = 0
- 填表顺序:对于
f
,因为要依赖f[i-1]
,所以填表顺序为从左向右;
对于g
,要依赖g[i+1]
,所以填表顺序为从右向左
这个时间复杂度为O(n)+O(n)+O(n),可理解为O(N)
🥔3. 代码实现
class Solution {
public:
int pivotIndex(vector<int>& nums)
{
int n = nums.size();
vector<int> f(n),g(n);
//处理前缀和数组
for(int i=1;i<n;i++)
f[i] = f[i-1] + nums[i-1];
//处理后缀和数组
for(int i=n-2;i>=0;i--)
g[i] = g[i+1] + nums[i+1];
//判断
for(int i=0;i<n;i++)
{
if(f[i]==g[i])
return i;
}
return -1;
}
};
力扣这个击败多少用户有时候是看网速的,如果算法没问题,多提交几次就行了,如果不在意,也可以忽略,没什么影响。