前缀和的综合应用(力扣C++题解)

目录

前缀和的作用:

构造前缀和的模板:

1:寻找数组的中心下标(简单)

2:逐步求和得到正数的最小值(简单)

3:找到最高海拔(简单)

4:所有奇数长度子数组的和(有点不简单)

5:检查是否区域内的所有整数都被覆盖(差分+前缀和)

6:长度最小的子数组(滑动窗口)

7:除自身以外数组的乘积

8:前缀和二维数组的应用

9:连续的子数组和(数学:同余定理+哈希)

10:连续数组(前缀和+哈希)

11:和为K的子数组(前缀和+哈希) 

12:和相同的二元子数组(前缀和哈希+滑动窗口)

13:和可被K整除的子数组(前缀和+哈希)

13:最大连续1的个数|||(前缀和+滑动窗口)


前缀和的作用:

能求出一段区间内的数的和(在O(1)的时间内)

如果构造的sum是(n大小且sum[0]=nums[i])  ans=sum[right]-sum[left-1]

 如果构造的sum是(n大小且sum[1]=nums[0]) ans=sum[right+1]-sum[left]


构造前缀和的模板:

n+1的模板:

class Solution {
public:
    vector<int> runningSum(vector<int>& nums) {
    int n=nums.size();
    vector<int> ans(n+1,0);
    
    for(int i=0;i<n;i++)
    {
        ans[i+1]=ans[i]+nums[i];
    }
    return ans;
    }
};

n的模板:

class Solution {
public:
    vector<int> runningSum(vector<int>& nums) {
    int n=nums.size();
    vector<int> ans(n+1,0);
    
    for(int i=0;i<n;i++)
    {
        ans[i+1]=ans[i]+nums[i];
    }
    return ans;
    }
};

1:寻找数组的中心下标(简单)

 思路解析:

中心下标:这个位置的左边的数之和==这个位置的右边的数之和

那么数组的总和为sum,就有组合公式leftsum+nums[i]+rightsum=sum

移项则有:leftsum=sum-rightsum-nums[i]

即我们只需求出sum,再遍历左侧前缀和即可

class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        int sum = 0;
        for (int num : nums) sum += num; // 求和
        int leftSum = 0;    // 中心索引左半和
        int rightSum = 0;   // 中心索引右半和
        for (int i = 0; i < nums.size(); i++) {
            leftSum += nums[i];
            rightSum = sum - leftSum + nums[i];
            if (leftSum == rightSum) return i;
        }
        return -1;
    }
};

2:逐步求和得到正数的最小值(简单)

 思路解析:

利用前缀和求出这个原数组nums对应的前缀和数组ans,题目要求的题意即可转变为将前缀和数组的最小值至少加上x,使得数组的每个数都大于或等于1

构造好前缀和数组后,我们初始化min=INT_MAX,求最小值,共有两种情况

如果min的值出来后大于等于1,那么证明前缀和数组都是正数,所以无需加上数字

如果min的值出来后小于1,那么就根据样例进行调整即可

class Solution {
public:
    int minStartValue(vector<int>& nums) {
    int Min=INT_MAX;
    int sum=0;
    for(int num:nums)
    {
        sum+=num;
        Min=min(Min,sum);
    }
    if(Min>=1) return 1;//证明数组中的数都是正数
    else return abs(Min)+1;//数组中存在负数
    }
};

3:找到最高海拔(简单)

 思路解析:

根据原数组构造出前缀和数组,并求出前缀和数组的最大值即可

class Solution {
public:
    int largestAltitude(vector<int>& gain) {
    int n=gain.size();
    vector<int> ans(n+1,0);
    for(int i=0;i<n;i++) ans[i+1]=ans[i]+gain[i];
    int MAX=INT_MIN;
    for(int i=0;i<n+1;i++)
    {
        if(ans[i]>MAX)
        {
            MAX=ans[i];
        }
    }
    return MAX;
    }
};

4:所有奇数长度子数组的和(有点不简单)

 思路解析:

有两条路的遍历方式:

 (1)像解释一样,先遍历1个1组的,再遍历3个1组的,再遍历5个一组的…………

(2)先遍历以1为头的所有奇数数组,比如1本身和[1,4,2]和[1,4,2,5,3],再遍历以2为头的

这里选择第一种遍历方式

(1)构造前缀和

(2)步长限制(step)(当步长大于等于这个数组长度时,跳出)

(3)for循环用i遍历,把nums[i]作为每个的头,并以步长的单位进行求区间和

(4)更新步长:step+=2;

class Solution {
public:
    int sumOddLengthSubarrays(vector<int>& arr) {
        int n=arr.size();
        vector<int> ans(n+1,0);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值