首页 > 其他分享 >【数组】前缀和

【数组】前缀和

时间:2023-01-15 00:00:42浏览次数:62  
标签:乘积 nums int sum 数组 前缀

前缀和

给出一个数列:

1 2 3 4 5 6 7 8 9 

它的前缀和:

1 3 6 10 15 21 28 36 45

前缀和即:从第一个元素到该元素之和

通常我们会在数组中触及到这类知识。
假设给出原数组 a[5] = {1,2,3,4,5},我们可以得到前缀和数组,假设为S[5] = {1,3,6,10,15}。
那么可以得到: S[n] = S[n-1] + a[n],即求前缀和的公式。

那么前缀和数组有什么用呢?

以下给出一道经典前缀和问题:

首先我们先从朴素思想开始考虑,求m次区间和的时间复杂度是O(mn2)

while(m--)
{
  int l , r;
  cin >> l >> r;
  int sum = 0;
  for(int i = l; i <= r; i++)
  {
      sum += num[i];(假设下标从1开始)
  }
  cout << sum << endl;
}

我们会发现,我们没求一次区间和,就要循环一次,那么有没有一种方法可以让O(n)的求和变为O(1)的时间复杂度呢?
答案就是使用前缀和。对区间[l,r],通过对求前缀和过程的分析可以的出,区间和为s[r]-s[l-1]。因此我们可以通过一次运算求出原数组任意一段数据的和。

以下为代码:

点击查看代码
#include<iostream>
#define N 100010
using namespace std;
int nums[N];
int s[N];
int main()
{
    int n,m;
    cin >> n >> m;
    for(int i = 0; i < n; i++)
    {    
        cin >> nums[i+1];
        s[i+1] = s[i] + nums[i+1];//求前缀和
    }
    while(m--)
    {
        int l,r;
        cin >> l >> r;
        cout << s[r]-s[l-1] << endl;//
    }
    return 0;
}


那么我们可以知道,前缀和通常在当我们需要对以区间为单位进行求和求乘积等操作时会用到。 ## 题目 ### 前缀和结合哈希表 ![](/i/l/?n=23&i=blog/2967764/202301/2967764-20230114233240573-1138750070.png) https://leetcode.cn/problems/subarray-sum-equals-k/
在数组中:
1.子数组
子数组的定义:一个或连续多个数组中的元素组成一个子数组(子数组最少包含一个元素)

2.子序列
子序列的定义:子序列就是在原来序列中找出一部分组成的序列(子序列不一定连续)

如果使用for嵌套循环暴力枚举O(n2)的方法必然会超时。
那么分析题意,可知求区间和为k的区间个数,即 s[i] - s[j] == k
同样,如果对前缀和数组进行枚举同样是O(n2)的时间复杂度,会超时。
我们用哈希表存储前缀和数组,结合公式s[i] - s[j] == k的变形s[j] = s[i] - k就可以实现O(n)的时间复杂度的解法。
即:对每一个前缀和数组元素s[i],利用哈希表查找s[i] - k是否存在,存在则找到了一个或n个符合题意的区间。
以下为代码

点击查看代码
class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int, int> mp;
        mp[0] = 1;
        int sum = 0;
        int ans = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            sum += nums[i];
            if(mp.find(sum - k) != mp.end())//
                ans += mp[sum - k];
            mp[sum]++;
        }
        return ans;
    }
};

前缀乘积



https://leetcode.cn/problems/subarray-sum-equals-k/

最先想到的是遍历求乘积,也就是O(n2)的暴力算法,但这不符合题目的要求。
那么我们需要对算法进行优化,从朴素思想出发,遍历求乘积时,从0到n-1累乘,中间跳过i,那么天然地由i分为左右两个区间,根据乘法的结合律,得出answer[i] = i左侧元素的乘积*i右侧元素的乘积。
那么我们只需要提前将每一个i左侧、右侧元素的乘积算出来,就可以实现O(n)时间复杂度的算法。

点击查看代码
class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> answer(n);
        vector<int> l(n);
        vector<int> r(n);
        l[0] = 1;
        r[n - 1] = 1;
        for(int i = 1; i < n; i++)
            l[i] = l[i-1]*nums[i-1];
        for(int i = n - 2; i >= 0; i--)
            r[i] = r[i+1]*nums[i+1];
        for(int i = 0; i < n; i++)
            answer[i] = l[i]*r[i];
        return answer;
    }
};
对于进阶要求,实现额外空间复杂度为O(1)的算法(不包括答案数组),那么只需要在答案数组上进行操作即可。先将i左侧元素的乘积存入答案数组,再将右侧元素的乘积乘进去,就大功告成。

标签:乘积,nums,int,sum,数组,前缀
From: https://www.cnblogs.com/he-zhan/p/17052750.html

相关文章

  • 定义一个长度为3的数组并打印改数组
    packagecom.fqs.demo;importjava.util.Arrays;publicclassChongZ{publicstaticvoidmain(String[]args){int[]array=newint[3];//......
  • 调用方法求数组中最大值
    先熟悉找3个值中的最大值packagecom.fqs.demo;publicclassChongZ{//求3个数的最大值并显示publicstaticvoidmain(String[]args){inta=......
  • LeetCode寻找两个正序数组的中位数(vector/二分查找 划分数组)
    原题解题目给定两个大小分别为m和n的正序(从小到大)数组nums1和nums2。请你找出并返回这两个正序数组的中位数。算法的时间复杂度应该为O(log(m+n))。约束......
  • 栈和堆的区别以及栈数组和堆数组的区别
    ​ 这里写得很简洁,实际上堆的机制比较复杂,我详细地学习了Windows下的堆管理机制,如果对这部分感兴趣的话,可以参考我的另一篇文章:https://www.cnblogs.com/XiuzhuKirakira/......
  • 遍历打印数组在一行 实例
    一行打印数组packagecom.fqs.demo;publicclassChongZ{//数组遍历遍历显示整个数组显示在一行//publicstaticvoidmain(String[]args){......
  • C++中如何将一行字符串(一行字符串可带空格)输入到string对象中或者字符数组中?
    提供两种方法:①、使用cin的成员函数getline,代码如下:charstr1[20];cin.getline(str1,20);     //第一个参数代表字符数组的指针,第二个参数代表写入的最大长度②、......
  • 数组是高效使用内存的基础
    数组是指多个同样数据类型的数据在内存中连续排列的形式。作为数组元素的各个数据会通过连续的编号被区分开来,这个编号称为索引(index)。指定索引后,就可以对该索引所对应地......
  • SA后缀数组
    SA后缀数组sa数组:sa[i]=x表示对于所有的后缀进行排序(字典序)后,得到排名为i的以第x个字符开头的后缀rk数组:rk[x]=i,是对于所有的后缀进行排序(字典序)后,得到以第x个字符......
  • 利用lodash对(对象)数组去重
    使用场景:根据数(对象)组中的id或者其他属性去重,或者对象中的所有属性值相同的去重。传统方法:通过数组的some进行逐项判断;用了lodash之后发现还是很香的。import{isEqual......
  • c++ 数组
              ......