当前位置: 首页 > article >正文

leetcode算法之前缀和

目录

  • 1.DP34[模板]一维前缀和
  • 2.DP35[模板]二维前缀和
  • 3.寻找数组的中心下标
  • 4.除自身以外数组的乘积
  • 5.和为K的子数组
  • 6.和可被K整除的子数组
  • 7.连续数组
  • 8.矩阵区域和

1.DP34[模板]一维前缀和

一维前缀和
在这里插入图片描述

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

int main()
{
    int n,q;
    cin>>n>>q;
    vector<long long> v(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>v[i];
    }
    //1.维护一个前缀和数组
    vector<long long> dp(n+1);
    for(int i=1;i<=n;i++)
    {
        dp[i]=dp[i-1]+v[i];
    }
    //2.使用前缀和数组
    int l,r;
    while(q--)
    {
        cin>>l>>r;
        cout<<dp[r]-dp[l-1]<<endl;
    }
    return 0;
}

2.DP35[模板]二维前缀和

二维前缀和
在这里插入图片描述

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

int main()
{
    int n,m,q;
    cin>>n>>m>>q;
    vector<vector<long long>>arr(n+1,vector<long long>(m+1));
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            cin>>arr[i][j];
        }
    }
    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-1][j]+dp[i][j-1]+arr[i][j]-dp[i-1][j-1];
        }
    }
    int x1,y1,x2,y2;
    while(q--)
    {
        cin>>x1>>y1>>x2>>y2;
        cout<<dp[x2][y2]-dp[x1-1][y2]-dp[x2][y1-1]+dp[x1-1][y1-1]<<endl;
    }
    return 0;
}

3.寻找数组的中心下标

寻找数组的中心下标
在这里插入图片描述

class Solution {
public:
    int pivotIndex(vector<int>& nums) {
        int n = nums.size();
        //1.维护一个前缀和和后缀和数组
        vector<int> f(n);
        for(int i=1;i<n;i++)
        {
            f[i] = f[i-1]+nums[i-1];
        }
        vector<int> g(n);
        for(int i=n-2;i>=0;i--)
        {
            g[i] = g[i+1]+nums[i+1];
        }
        //2.使用前缀和和后缀和数组
        for(int i=0;i<n;i++)
        {
            if(f[i] == g[i])
            {
                return i;
            }
        }
        return -1;
    }
};

4.除自身以外数组的乘积

除自身以外数组的乘积
在这里插入图片描述

class Solution {
public:
    vector<int> productExceptSelf(vector<int>& nums) {
        int n = nums.size();
        vector<int> f(n);
        f[0] = 1;
        for(int i=1;i<n;i++)
        {
            f[i] = f[i-1]*nums[i-1];
        }
        vector<int> g(n);
        g[n-1] = 1;
        for(int i = n-2;i>=0;i--)
        {
            g[i] = g[i+1]*nums[i+1];
        }
        vector<int> ret(n);
        for(int i=0;i<n;i++)
        {
            ret[i] = f[i]*g[i];
        }
        return ret;
    }
};

5.和为K的子数组

和为K的子数组
在这里插入图片描述

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 x:nums)
        {
            sum+=x;
            if(hash.count(sum-k)) ret+=hash[sum-k];
            hash[sum]++;
        }
        return ret;
    }
};

6.和可被K整除的子数组

和可被K整除的子数组
在这里插入图片描述

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k) {
        //前缀和+哈希表
        unordered_map<int,int> hash;
        hash[0%k] = 1;

        int ret = 0,sum = 0;
        for(auto x:nums)
        {
            sum+=x;
            int r = (sum%k+k)%k;
            if(hash.count(r)) ret+=hash[r];
            hash[r]++;
        }
        return ret;
    }
};


7.连续数组

连续数组
在这里插入图片描述

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        //前缀和+哈希表
        //哈希表里面存储的是前缀和和对应的下标
        unordered_map<int,int> hash;
        hash[0] = -1;

        int sum = 0,ret = 0;
        for(int i=0;i<nums.size();i++)
        {
            sum+=nums[i]==0?-1:1;
            if(hash.count(sum)) ret = max(ret,i-hash[sum]);
            else hash[sum] = i;
        }

        return ret;
    }
};

8.矩阵区域和

矩阵区域和
在这里插入图片描述

class Solution {
public:
    vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
        int m = mat.size(),n = mat[0].size();
        //二维前缀和+dp数组
        vector<vector<int>> dp(m+1,vector<int>(n+1));
        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]+mat[i-1][j-1]-dp[i-1][j-1];
            }
        }
        //使用前缀和数组dp
        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;
    }
};

http://www.kler.cn/a/136386.html

相关文章:

  • 2025-01-06日SSH钓鱼日志
  • 在ubuntu上如何使用sdkman安装两个版本的java并进行管理和维护
  • 【json】
  • “深入浅出”系列之FFmpeg:(1)音视频开发基础
  • Vue2: el-table为每一行添加超链接,并实现光标移至文字上时改变形状
  • Unity:删除注册表内的项目记录
  • 【小呆的力学笔记】有限元专题之循环对称结构有限元原理
  • Azure 机器学习 - 搜索中的检索增强 (RAG)
  • Selenium IDE录制脚本
  • macos苹果电脑清理软件有哪些?cleanmymac和腾讯柠檬哪个好
  • 【MISRA C 2012】Rule 4.2 不应该使用三连符
  • 最强英文开源模型Llama2架构与技术细节探秘
  • ChatGPT API 学习
  • C#,数值计算——插值和外推,分段线性插值(Linear_interp)的计算方法与源程序
  • Nginx - 本机读取服务器图像、视频
  • 《 机器人基础 》期末试卷(A)
  • SpringBoot中日志的使用log4j
  • 【腾讯云云上实验室-向量数据库】探索腾讯云向量数据库:全方位管理与高效利用多维向量数据的引领者
  • Ubuntu18.04安装IgH主站
  • 深入理解 @TableName 和 @TableField 注解
  • Python 技巧大揭秘,网络时间和本地时间轻松搞定
  • Java基础-----StringBuffer和StringBuilder
  • (十二)Flask重点之session
  • 【练习】检测U盘并自动复制内容到电脑的软件
  • Linux latin1字符集转成UTF-8
  • Vue3中使用Element-Plus分页组件