算法专题四:前缀和

这篇具有很好参考价值的文章主要介绍了算法专题四:前缀和。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一.一维前缀和(模板):

算法专题四:前缀和,算法,c++
一维前缀和

1.思路一:暴力解法

1.输入数组长度n和查询次数q。
2.使用一个一维数组保存数据。
3.使用一个循环获取q次需要查询范围的数据。
4.遍历r-l+1次进行一个范围求和然后输出。
5.时间复杂度:O(n^2)
6.通过不了所有的测试用例。

2.思路二:前缀和思路

1.输入数组长度n和查询次数q。
2.使用一个一维数组保存数据。
3.构建一个前缀和的一个数组。
算法专题四:前缀和,算法,c++
4.使用一个循环获取q次需要查询范围的数据。
5.时间复杂度:O(n^2)
6.通过不了所有的测试用例。

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    //1.输入数组长度和查询次数: 
    int n =0,q=0;
    cin>>n>>q;
    //2.输入数组数据:
    vector<int> arr(n+1);
    for(int i=1;i<=n;i++) cin>>arr[i];
    //3.前缀和数组:
    vector<long long> bp(n+1);
    for(int i=1;i<=n;i++) bp[i] = bp[i-1] + arr[i];
    //4.计算和:
    int i=0,r=0;
    while(q!=0)
    {
        cin>>i>>r;
        cout<<(bp[r] - bp[i-1])<<endl;
        q--;
    }
}

二. 二维前缀和(模板):

算法专题四:前缀和,算法,c++
二维前缀和

1.思路一:构造前缀和数组

算法专题四:前缀和,算法,c++

#include <iostream>
#include <vector>
using namespace std;

int main()
{
    //1.n行m列的一个二维数组:
    int n = 0, m = 0, q = 0;
    cin >> n >> m >> q;
    //2.数组输入数据:
    vector<vector<int>> vv((n + 1),vector<int>(m+1));
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)cin >> vv[i][j];
    }

    //3.创造二维的求和dp数组
    vector<vector<long long>> dp((n + 1), vector<long long>(m + 1));
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= m; j++)
        {
            dp[i][j] = ((dp[i][j - 1] + dp[i - 1][j]) - dp[i-1][j-1]) + vv[i][j];
        }
    }
    //4.数据查询:

    while (q != 0)
    {
        int x1 = 0, y1 = 0, x2 = 0, y2 = 0;
        cin >> x1 >> y1 >> x2 >> y2;

        cout << (dp[x2][y2] - (dp[x1 - 1][y2] + dp[x2][y1-1]) + dp[x1-1][y1-1]) << endl;
        q--;
    }


}

三.寻找数组的中心下标:

算法专题四:前缀和,算法,c++

寻找数组的中心下标

1.思路一:前缀和

算法专题四:前缀和,算法,c++

class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        
        //1.构建前缀和数组:
        int n = nums.size();
        vector<int> dp(n+1);
        //2.前缀和数组值遍历:
        for(int i = 1 ; i<=n;i++) dp[i] = dp[i-1] + nums[i-1];

        //3.进行中心下标的寻找:
        int mid = -1;
        for(int i=1 ; i <= n ; i++)
        {
            if((dp[i-1] - dp[0]) == (dp[n] - dp[i]))
            {
                mid = i-1;
                break;
            }
        }
        //4.没有中心下标的情况:
        return (mid == -1? -1:mid);
    }
};

四.除自身以外数组的乘积:

算法专题四:前缀和,算法,c++

除自身以外数组的乘积

1.思路一:暴力解法

算法专题四:前缀和,算法,c++

2.思路二:前缀积+后缀积

算法专题四:前缀和,算法,c++

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {

        //1.前缀积+后缀积
        int n = nums.size();
        vector<int> left(n + 1, 1);
        vector<int> right(n + 1, 1);

        //2.遍历确定前缀积+后缀积的值:
        for (int i = 1; i <= n; i++) left[i] = left[i - 1] * nums[i - 1];
        for (int i = n - 1; i >= 0; i--) right[i] = right[i + 1] * nums[i];

        // 1  1  2  6  24
        // 24 24 12 4  1
        // 0  1  2  3  4

        //0   1   2  3
        //24  12  8  6
        vector<int> ret(n);
        //3.遍历ret数组并且赋值
        for (int i = 0; i < n; i++)
        {
            ret[i] = left[i] * right[i+1];
        }

        return ret;
    }
};

五.和为K的子数组:

算法专题四:前缀和,算法,c++

和为K的子数组

1.思路一:前缀和+哈希

算法专题四:前缀和,算法,c++

class Solution {
public:
    int subarraySum(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0]=1;
        int sum = 0 , ret = 0;
        for(auto n : nums)
        {
            sum+=n;
            if(hash.count(sum-k)) ret+=hash[sum-k];
            hash[sum]++;
        }
        return ret;
    }
};

六.前缀和可以被K整除的子数组:

算法专题四:前缀和,算法,c++

前缀和可以被K整除的子数组

1.思路一:前缀和+哈希

算法专题四:前缀和,算法,c++

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        unordered_map<int,int> hash;
        hash[0] = 1;

        //1.开始遍历+判断
        int sum = 0 , ret = 0;
        for(auto a : nums)
        {
            sum+=a;
            int n = (sum%k + k) % k;

            if(hash.count(n)) ret+=hash[n];
            hash[n]++;
        }
        return ret;
    }
};

七.连续数组:

算法专题四:前缀和,算法,c++

连续数组

1.思路一:

算法专题四:前缀和,算法,c++

算法专题四:前缀和,算法,c++

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        vector<int> nums_1(nums);
        for(auto& n:nums_1)
        {
            if(n==0) n = -1;
        }

        //2.hash+前缀和的思路
        unordered_map<int,int> hash;
        //1.前缀和为0的下标处理:
        hash[0] = -1;
        int sum = 0,ret = 0;
        for(int i=0;i<nums.size();i++)
        {
            sum+=nums_1[i];
            if(hash.count(sum)) ret = max(ret , i - hash[sum]);
            else hash[sum] = i;
        }
        return ret;
    }
};

八.矩阵区域和:

算法专题四:前缀和,算法,c++

矩阵区域和

1.思路一:二维前缀和模板+细节处理

算法专题四:前缀和,算法,c++文章来源地址https://www.toymoban.com/news/detail-788774.html

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m = mat.size();
        int n = mat[0].size();

        //1.创建(m+1) * (n+1) 大小的二维数组
        vector<vector<int>> dp(m+1 , vector<int>(n+1));

        //2.dp数组赋值:
        for(int i=1 ; i<=m ; i++)
        {
            for(int j=1 ; j<=n ; j++)
            {
                dp[i][j] = dp[i-1][j] + dp[i][j-1] - dp[i-1][j-1] + mat[i-1][j-1];
            }
        }

        //3.使用dp数组并且考虑i-k 和 j-k的越界问题:
        vector<vector<int>> ret(m,vector<int>(n));

        for(int i=0 ; i<m ; i++)
        {
            for(int j=0 ; j<n ; j++)
            {
                int x1 = max(0, i - k) + 1, y1 = max(0, j - k) + 1;
                int x2 = min(m - 1, i + k) + 1, y2 = min(n - 1, j + k) + 1;
                
                ret[i][j] = dp[x2][y2] - dp[x1 - 1][y2] - dp[x2][y1 - 1] +
                    dp[x1 - 1][y1 - 1];
            }
        }
        return ret;
     }
};

到了这里,关于算法专题四:前缀和的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 每天一道算法练习题--Day18 && 第一章 --算法专题 --- ----------前缀树

    字典树也叫前缀树、Trie。它本身就是一个树型结构,也就是一颗多叉树,学过树的朋友应该非常容易理解,它的核心操作是插入,查找。删除很少使用,因此这个讲义不包含删除操作。 截止目前(2020-02-04) 前缀树(字典树) 在 LeetCode 一共有 17 道题目。其中 2 道简单,8 个

    2024年02月02日
    浏览(37)
  • 前缀和算法(类似于动态规划算法)

    前缀和:在一些特定的题里面,要先把 一段连续的数的和 先算出来,用 数组来接收 ,然后 利用这个数组 返回题目需要的答案 干讲无力 题目解释更好 请往下看 题目:题目链接 题目解析: 在数组中找到一个下标,划分为2个区间 左区间的和=右区间的和,如果没有这个下标则返

    2024年02月04日
    浏览(29)
  • 【算法小课堂】深入理解前缀和算法

    前缀和是指某序列的前n项和,可以把它理解为数学上的数列的前n项和,而差分可以看成前缀和的逆运算。合理的使用前缀和与差分,可以将某些复杂的问题简单化。 我们通过一个例子来理解前缀和算法的优势: www.nowcoder.com 我们可以通过暴力的解法去解决这个问题,但是这

    2024年02月08日
    浏览(30)
  • 【数据结构与算法】前缀和+哈希表算法

    关于前缀和和哈希这两个概念大家都不陌生,在之前的文章中也有过介绍:前缀和与差分算法详解 而哈希表最经典的一题莫过于 两数之和 题目链接 题目描述: 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它

    2024年02月01日
    浏览(103)
  • 一、二维前缀和算法

    一维前缀和: 二维前缀和: 给你一个整数数组 nums ,请计算数组的 中心下标 。 数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。 如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中

    2024年02月16日
    浏览(25)
  • 前缀和算法【一维、二维】

    首先这种算法适合于求 从 x 到 y 的和 。 一维代码十分简单,我们只需要每个都记录前面所有的和即可,注意细节 下标从1开始 这里我们就看两种情况:一种是 开始时 ,一种是 执行中 在开始时,因为我们是从1开始,a[0] = 0,所以第一个就是temp; 在执行过程中,因为前一个是

    2023年04月18日
    浏览(24)
  • Java前缀和算法

    通俗来讲,前缀和算法就是使用一个新数组来储存原数组中前n-1个元素的和(如果新数组的当前元素的下标为n,计算当前元素的值为原数组中从0到n-1下标数组元素的和),可能这样讲起来有点抽象,我们举一个例子对其进行说明:给定一个数组nums[],我们创建一个大小为num

    2024年02月06日
    浏览(38)
  • 算法(4)——前缀和

    目录 一、前缀和的定义 二、一维前缀和 三、一维前缀和OJ题 3.1、前缀和 3.2、寻找数组中心下标 3.3、除自身以外数组的乘积 3.4、和为K的数组 3.5、和可被K整除的子数组 3.6、连续数组 四、二位前缀和 4.1、二维前缀和 4.2、矩阵区域和 对于一个给定的数列A,他的前缀和数中 

    2024年01月24日
    浏览(24)
  • 前缀和算法

    题目链接:前缀和 算法思路 先预处理出来⼀个「前缀和」数组: ⽤ dp[i] 表⽰: [1, i] 区间内所有元素的和,那么 dp[i - 1] ⾥⾯存的就是 [1, i - 1] 区间内所有元素的和,那么:可得递推公式: dp[i] = dp[i - 1] + arr[i] ; 使⽤前缀和数组,「快速」求出「某⼀个区间内」所有元素的

    2024年02月22日
    浏览(27)
  • 「算法」前缀和

    前缀和主要解决求数组中某段区间 元素和 的问题 ,使用前缀和解决问题的步骤如下: 预处理一个前缀和数组 使用这个数组 现在有一个一维数组 nums 预处理前缀和数组 定义一个数组 dp[] , dp[i] 表示 nums 中 [0,i-1] 区间的元素和,那我们就有 dp[i] == dp[i-1] + nums[i-1] 这个递推关系

    2024年03月13日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包