刷题训练之前缀和

 > 作者:დ旧言~
> 座右铭:松树千年终是朽,槿花一日自为荣。

> 目标:熟练掌握前缀和算法。

> 毒鸡汤:学习,学习,再学习 ! 学,然后知不足。

> 专栏选自:刷题训练营

> 望小伙伴们点赞👍收藏✨加关注哟💕💕 

🌟前言分析

        最早博主续写了牛客网130道题,这块的刷题是让同学们快速进入C语言,而我们学习c++已经有一段时间了,知识储备已经足够了但缺少了实战,面对这块短板博主续写刷题训练,针对性学习,把相似的题目归类,系统的刷题,而我们刷题的官网可以参考:​​​​​​

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网

⭐知识讲解

前缀和只是一个算法的总称,其实前缀和可以分为前缀和,前缀积,这类算法更像是高中我们所学的数列的求和,寻找一组数列的规律,从而计算前缀和,这类题目很有规律的,学会画图,掌握题目的所隐藏的规律,这类题目就自然而然的可以解出。

⭐经典题型

🌙topic-->1

题目链接:1.前缀和

题目分析:

输入  n  个数字 ,求 q 次前缀和,这个 q 次前缀和范围在 l ~ r 之间 (不是数组的下标,而是数组第l 的数),输出多组数据。

算法原理:

  • 解法一:

暴力遍历数组,时间复杂度为O(n * q),这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用前缀和的算法原理:

代码演示:

#include <iostream>
using namespace std;

const int N = 100001; // 数据大小
long long arr[N],dp[N];
int n,q; 

int main() 
{
    // 输入
    cin >> n >> q;
    // 存入数据
    for(int i = 1;i <= n;i++)
        cin >> arr[i];
    // 前缀和
    for(int i = 1;i <= n;i++)
        dp[i] = dp[i - 1] + arr[i];
    // 输出
    while(q--)
    {
        int l,r = 0;
        cin >> l >> r;
        // 计算前缀和
        cout << dp[r] - dp[l - 1] << endl;
    }
    return 0;
}

 🌙topic-->2

题目链接:2二维前缀和

题目分析:

在一个二维数组( n  *  m)中,求 q 次二维前缀和,其中需要输入两个二维坐标,求输入这个两个坐标矩阵的和。

算法原理:

  • 解法一:

暴力遍历二维数组,时间复杂度为O(n * m  * q),这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用二维前缀和的算法原理:

代码演示:

#include <iostream>
using namespace std;

const int N = 1001; // 数据大小
int arr[N][N];
long long dp[N][N];
int n,m,q = 0;

int main() 
{
    // 输入
    cin >> n >> m >> q;
    // 读入数据
    for(int i = 1 ;i <= n;i++)
        for(int j = 1;j <= m;j++)
            cin >> arr[i][j];
    // 处理数据
    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 = 0;
    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;
}

 🌙topic-->3

题目链接:3.前缀和

题目分析:

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

算法原理:

  • 解法一:

暴力遍历一维数组,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用一维前缀和的算法原理:

代码演示:

class Solution {
public:
	int pivotIndex(vector<int>& nums) 
    {
		// lsum[i] 表⽰:[0, i - 1] 区间所有元素的和
		// rsum[i] 表⽰:[i + 1, n - 1] 区间所有元素的和
		int n = nums.size();
		vector<int> lsum(n), rsum(n);
		// 预处理前缀和后缀和数组
		for (int i = 1; i < n; i++)
			lsum[i] = lsum[i - 1] + nums[i - 1];
		for (int i = n - 2; i >= 0; i--)
			rsum[i] = rsum[i + 1] + nums[i + 1];
		// 判断
		for (int i = 0; i < n; i++)
			if (lsum[i] == rsum[i])
				return i;
		return -1;
	}
};

 🌙topic-->4

题目链接:4.前缀和

题目分析:

给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。

算法原理:

  • 解法一:

暴力遍历一维数组,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用一维前缀积的算法原理:

代码演示:

class Solution
{
public:
	vector<int> productExceptSelf(vector<int>& nums)
	{
		// lprod 表⽰:[0, i - 1] 区间内所有元素的乘积
		// rprod 表⽰:[i + 1, n - 1] 区间内所有元素的乘积
		int n = nums.size();
		vector<int> lprod(n + 1), rprod(n + 1);
		lprod[0] = 1, rprod[n - 1] = 1;
		// 预处理前缀积以及后缀积
		for (int i = 1; i < n; i++)
			lprod[i] = lprod[i - 1] * nums[i - 1];
		for (int i = n - 2; i >= 0; i--)
			rprod[i] = rprod[i + 1] * nums[i + 1];
		// 处理结果数组
		vector<int> ret(n);
		for (int i = 0; i < n; i++)
			ret[i] = lprod[i] * rprod[i];
		return ret;
	}
};

 🌙topic-->5

题目链接:5.前缀和

题目分析:

给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。

算法原理:

  • 解法一:

暴力遍历一维数组,定住一个元素向后寻找,时间复杂度为 O(n*n) ,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用一维前缀和的算法原理:

代码演示:

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 = sum + x;// 累计起来
            if(hash.count(sum - k)) // 模拟指针向后移
                ret = ret + hash[sum - k];
            hash[sum]++;
        }
        return ret;
    }
};

🌙topic-->6

题目链接:6.前缀和

题目分析:

给定一个整数数组 nums 和一个整数 k ,返回其中元素之和可被 k 整除的(连续、非空) 子数组 的数目。

子数组 是数组的 连续 部分。

算法原理:

  • 解法一:

暴力遍历一维数组,定住一个元素向后寻找,时间复杂度为 O(n*n) ,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用一维前缀和的算法原理:

代码演示:

class Solution {
public:
    int subarraysDivByK(vector<int>& nums, int k)
    {
        unordered_map<int, int> hash;
        hash[0 % k] = 1; // 0 这个数的余数
        int sum = 0, ret = 0;
        for (auto x : nums)
        {
            sum += x; // 算出当前位置的前缀和
            int r = (sum % k + k) % k; // 修正后的余数
            if (hash.count(r)) ret += hash[r]; // 统计结果
            hash[r]++;
        }
        return ret;
    }
};

🌙topic-->7

题目链接:7.前缀和

题目分析:

给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。

  • nums[i] 不是 0 就是 1

算法原理:

  • 解法一:

暴力遍历一维数组,定住一个元素向后寻找,时间复杂度为 O(n*n) ,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用一维前缀和的算法原理:

代码演示:

class Solution
{
public:
	int findMaxLength(vector<int>& nums)
	{
		unordered_map<int, int> hash;
		hash[0] = -1; // 默认有⼀个前缀和为 0 的情况
		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;
	}
};

🌙topic-->8

题目链接:8.前缀和

题目分析:

给你一个 m x n 的矩阵 mat 和一个整数 k ,请你返回一个矩阵 answer ,其中每个 answer[i][j] 是所有满足下述条件的元素 mat[r][c] 的和。

算法原理:

  • 解法一:

暴力遍历二维数组,定住一个元素向后寻找,时间复杂度为 O(n*n) ,这个解法会超时,所以我们不用这个算法。

  • 解法二:

采用二维前缀和的算法原理:(和第二题相似)

代码演示:

class Solution {
public:
	vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) {
		int m = mat.size(), n = mat[0].size();
		vector<vector<int>> dp(m + 1, vector<int>(n + 1));
		// 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] - dp[i - 1][j - 1] +
				mat[i - 1][j - 1];
		// 2. 使⽤
		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.mfbz.cn/a/578181.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

物联网的基本功能及五大核心技术——青创智通

工业物联网解决方案-工业IOT-青创智通 物联网基本功能 物联网的最基本功能特征是提供“无处不在的连接和在线服务”&#xff0c;其具备十大基本功能。 &#xff08;1&#xff09;在线监测&#xff1a;这是物联网最基本的功能&#xff0c;物联网业务一般以集中监测为主、控制为…

Vitis HLS 学习笔记--C/C++ static 关键字的作用

目录 1. 简介 2. c/c共有性质 3. c独有性质 4. 示例说明 5. static 对于 HLS 工具的影响 6. 总结 1. 简介 在Vitis HLS中&#xff0c;偶尔会用到 static 关键字。考虑到Vitis HLS同时兼容C和C语言&#xff0c;有必要理解这两种语言中static关键字细微差异。本文旨在梳理…

Centos7.9系统MySQL5.7.32升级为5.7.44(生成环境操作)

1.背景 由于客户进行等保漏扫和渗透&#xff0c;生成环境mysql数据库被扫描出了 高危漏洞。 如图&#xff1a;部分漏洞 查看漏洞详细信息&#xff0c;建议升级到指定版本解决&#xff1a; 说明&#xff1a; 本文仅适合使用当前数据库为 RPM 安装方式 2.升级前准备 查看环…

串口服务器可以直接连接工业路由器吗

串口服务器可以直接连接工业路由器吗 在工业物联网的架构中&#xff0c;串口服务器和工业路由器都是不可或缺的重要组件。串口服务器的主要功能是将串口通信转换为网络通信&#xff0c;实现数据的远程传输和管理&#xff1b;而工业路由器则负责在工业环境中提供稳定、可靠的网…

QT入门:计算圆面积的QT开始以及日历相关

QT入门&#xff1a;计算圆面积的QT开始以及日历相关 使用的工具为Qt creator 如图所示的为Qt的一个基本目录&#xff0c;首先打开mainwindow.ui进行设计&#xff0c;首先是讲解日历的&#xff0c;可以完全不用写代码&#xff0c;只在mainwindow.ui即可实现。 这是最后的一个成…

YES-2000B数显压力试验机技术方案书

一、简介 本机采用主机与液压系统集于一体的结构形式&#xff0c;结构紧凑&#xff0c;小巧玲珑。采用液压加荷、电子测力&#xff0c;具有加荷数率显示&#xff0c;峰值保持等功能&#xff0c;并配有微型打印机。 外观示意图 二、 液压系统 油箱内的液压油通过电机带动高压…

带宽内存服务器爆满,阿里云木马排查过程

服务器的连接数和带宽都暴增&#xff0c;导致项目直接宕机&#xff0c;无法使用的解决方案。 查看服务器实时流量 服务器内执行命令&#xff1a; yum install iftop -y iftop -Pn查看日志&#xff0c;发现服务器在对外访问 .148.232.186 的443端口。 于是设置安全组出方…

前端HTML5学习1(新增布局,状态,列表,文本,表单控件标签)

前端HTML5学习1&#xff08;新增布局&#xff0c;状态&#xff0c;列表&#xff0c;文本&#xff0c;表单控件标签&#xff09; 新增布局标签新增状态标签新增列表标签新增文本标签新增表单控件属性input新增属性值 新增布局标签 HTML5 引入了许多新的语义化标签&#xff0c;用…

各省铁路里程、公路里程、交通网密度面板数据(2000-2022年)

01、数据简介 铁路里程是指铁路线从起点到终点的公里数&#xff0c;通常用于表示铁路线路的长度。 公路里程是指一定时期内实际达到《公路工程技术标准》规定的等级公路&#xff0c;并经公路主管部门正式验收交付使用的公路里程数。 交通网密度是指某一区域内交通线路的密集…

直播任我行,智享AI自动直播手机塑造直播新风潮,引领行业“风口”

直播任我行&#xff01;智享AI自动直播手机塑造直播新风潮&#xff0c;引领行业“风口”&#xff01; 直播作为一种受欢迎的互联网传播方式&#xff0c;如今在帮助商家推广产品并获得更多收益方面发挥着重要作用。 在直播电商领域&#xff0c;主播是连接品牌和用户之间的关键纽…

js如何点击生成4位随机数

效果图&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width, initial-scale1.0"> <title>Generat…

15(第十四章,大数据和数据科学)

目录 概述 基本概念 数据仓库/传统商务智能与数据科学的比较 数据科学的过程 大数据 大数据来源 数据湖 机器学习 监督学习 无监督学习 强化学习 扩展 1、数据仓库&#xff08;Data Warehouse&#xff09; 2、数据湖(Data Lake) 3、大数据平台1.0 4、数据中台 …

2024蓝桥杯CTF--逆向

蓝桥杯付费CT--逆向 题目&#xff1a;RC4题目&#xff1a;happytime总结&#xff1a; 题目&#xff1a;RC4 先查壳&#xff0c;无壳&#xff0c;并且是32位&#xff1a; 用32位的ida打开&#xff0c;直接定位到main函数&#xff1a; 重点关注sub_401005函数&#xff0c;这个应…

基于Kubernetes部署free5gc核心网

说明&#xff1a; 本文仅适合个人对5gc核心网感兴趣测、研究使用。 操作系统版本&#xff1a; # uname -r 5.4.0-177-generic # lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 20.04.5 LTS Release: 20.04 Codename: …

spring boot3单模块项目工程搭建-上(个人开发模板)

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 上文衔接 常规目录创建 common目录 exception.handle目录 result.handle目录 controller目录 service目录 mapper目录 entity目录 test目录 写在最后 写在前面 本文…

CSS学习(选择器、盒子模型)

1、CSS了解 CSS&#xff1a;层叠样式表&#xff0c;一种标记语言&#xff0c;用于给HTML结构设置样式。 样式&#xff1a;文字大小、背景颜色等 p标签内不能嵌套标题标签。 px是相对于分辨率而言的&#xff0c; em是相对于浏览器的默认字体&#xff0c; rem是相对于HTML根元…

更易使用,OceanBase开发者工具 ODC 4.2.4 版本升级

亲爱的朋友们&#xff0c;大家好&#xff01;我们的ODC&#xff08;OceanBase Developer Center &#xff09;再次迎来了重要的升级V 4.2.4&#xff0c;这次我们诚意满满&#xff0c;从五个方面为大家精心打造了一个更加易用、贴心&#xff0c;且功能更强的新版本&#xff0c;相…

如何写好代码?

文章目录 前言内容代码应当易于理解命名注释格式循环和逻辑设计函数设计类其它&#xff08;编程规范、静态检查工具&#xff09;重构 前言 在软件开发领域&#xff0c;写好代码是至关重要的一环。不论是在学校学习的学生&#xff0c;刚刚毕业的应届生&#xff0c;还是刚步入企…

JAVA SWING JTABLE表格,点击表头数据可以排序,且第一二行位置固定,不参与排序

对于JAVA SWING 界面开发&#xff0c;使用表格JTABLE开发过程中&#xff0c;一些情况下可能需要在点击表头时对数据进行排序处理。对于简单的排序处理&#xff0c;jtable的setAutoCreateRowSorter方法可满足&#xff0c;但是对于高要求的排序&#xff0c;则满足不了。 比如&am…

《html自用使用指南》--基于w3School实践

1.基础标签 文本输入时&#xff0c;在编辑器中的换行&#xff0c;多个空格&#xff0c;都被编辑器看作一个空格 <p> 这个段落 在源代码 中 包含 许多行 但是 浏览器 忽略了 它们。 </p>结果&#xff1a;这个段落 在源代码 中 包含 许多行 但是 浏览器…
最新文章