前缀和——724. 寻找数组的中心下标

前缀和——724. 寻找数组的中心下标_第1张图片

文章目录

    • 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),这里就不作示例了。
前缀和——724. 寻找数组的中心下标_第2张图片

解法二:前缀和

我们可以用前缀和的思想来优化这个暴力解法

不要笨重的记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]

前缀和——724. 寻找数组的中心下标_第3张图片

有了前缀和与后缀和数组,我们直接判断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;
    }
};

力扣这个击败多少用户有时候是看网速的,如果算法没问题,多提交几次就行了,如果不在意,也可以忽略,没什么影响。
前缀和——724. 寻找数组的中心下标_第4张图片

你可能感兴趣的:(刷题,原创,前缀和,算法,c++,力扣)