前缀和练习

【模版】前缀和

【模板】前缀和_牛客题霸_牛客网

思路

要想快速找出某一连续区间的和,我们就要使用前缀和算法。

其实本质是再创建一个dp数组,每进一次循环加上原数组的值(dp代表arr的前n项和):

vector<int> arr(n + 1);
for(int i = 1; i <= n; i++) cin >> arr[i];vector<long long> dp(n + 1);
for(int i = 1; i <= n; i++) dp[i] = dp[i - 1] + arr[i];

为防止i取0时i-1等于-1,我们从i = 1开始,当i等于0时数组值默认为0相加不会改变其值。

而我们需要某一特定区间的和,将dp数组的dp[r] - dp[l - 1]即可,例如我要求2到4区间用dp[4]-dp[1]即可:
 

代码

#include <iostream>
#include <vector>
using namespace std;int main() 
{int n = 0, q = 0;cin >> n >> q;vector<int> arr(n + 1);for(int i = 1; i <= n; i++) cin >> arr[i];vector<long long> dp(n + 1);for(int i = 1; i <= n; i++) dp[i] = dp[i - 1] + arr[i];int l = 0, r = 0;while(q--){cin >> l >> r;cout << dp[r] - dp[l - 1] << endl;}return 0;
}

【模板】二维前缀和 

【模板】二维前缀和_牛客题霸_牛客网

思路

本题暴力解法即为题目要求什么就求什么,时间复杂度为O(n*m*q)。因为此题为求某一区间的和,所以我们想到使用前缀和解题,本题为二维数组,所以是二维前缀和。

解法分为三步:第一步,读入数据

int n = 0, m = 0, q = 0;
cin >> n >> m >> q;
vector<vector<int>> arr(n + 1, vector<int>(m + 1));
for (int i = 1; i <= n; i++)
    for (int j = 1; j <= m; j++)
        cin >> arr[i][j];

 第二步,预处理

创建一个dp二维数组,将arr的前n项和加起来,将dp分为四份即为总面积,其中BC宽度均为1,。为方便求面积,我们用(A + B) + (A + C) + D - A来表示总面积。A+B是dp[i-1][j] B+C是dp[i][j-1],D即为arr[i][j].A即为dp[i-1][j-1].

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];

 第三步,使用前缀和矩阵

如预处理,求某一块的面积,例如(x1, y1)到(x2, y2),即为A+B+C+D-(A+B)-(A+C)+A : dp[x2][y2] - dp[x1-1][y2] - dp[x2][y1-1] + dp[x1-1][y1-1].

代码

#include <iostream>
#include <vector>
using namespace std;int main()
{//读入数据int n = 0, m = 0, q = 0;cin >> n >> m >> q;vector<vector<int>> arr(n + 1, vector<int>(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 = 0, y1 = 0, x2 = 0, 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;
}

寻找数组的中心下标

724. 寻找数组的中心下标 - 力扣(LeetCode)

思路

我们要让左边之和等于右边之和,我们创建两个dp数组分别存放左右两边数字之和,并分别记作f, g。f[i] = f[i - 1] + nums[i - 1], 并且由于存在i - 1,所以 i需要从1开始,否则就会出现f[-1]的情况;

同理,右边之和g[j] = g[j + 1] + nums[j +1], 并且由于存在i + 1,所以j需要从n - 2开始,否则就会出现f[n]的情况。

代码

int pivotIndex(vector<int>& nums)
{int n = nums.size();vector<int> f(n), g(n);//预处理前缀和数组和后缀和数组for (int i = 1; i < n; i++)f[i] = f[i - 1] + nums[i - 1];for (int j = n - 2; j >= 0; j--)g[j] = g[j + 1] + nums[j + 1];//使用for (int i = 0; i < n; i++)if (f[i] == g[i]) return i;return -1;
}

除自身以外数组的乘积

238. 除自身以外数组的乘积 - 力扣(LeetCode)

思路

与上一题类似,要求除次下标外其他数的乘积,我们将其转化为i左边乘积乘上右边乘积即可:

左:f[i] = f[i - 1] * nums[i - 1]

右:g[j] = g[j + 1] * nums[j +1]

需要注意的是f[0]和g[n - 1]的初始值是0,这样会导致所求得的值都为0, 所以与上一题不同的是,我们需要将f[0]和g[n - 1]的初始值设为1,这样就不会影响所求得的值了。

代码

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

和为k的子数组

560. 和为 K 的子数组 - 力扣(LeetCode)

思路

取中间点m,m到i即为所要的区间,可以转化为计算0到m区间之和,和为sum - k。通过计算前缀和等于sum-k即可判断要求区间等于K,我们将前缀和放入不重复的哈希表中,最后通过hash.count()返回子数组的个数。

代码

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;}

和可被K整除的子数组

974. 和可被 K 整除的子数组 - 力扣(LeetCode)

思路

本题需要补充两个相关知识:

余数定理

若两个数之差可被k整除(模k等于0),则两个数模k的值相等

c++和java负数模k

c++和java负数模k还是负数,所以我们需要用下面的式子将其修正(变为正数):a % k = (a % k + k) % k.

了解这两个知识,本题就与上题极其相似,只不过是sum-k变成了sum模k了。

代码

    int subarraysDivByK(vector<int>& nums, int k) {unordered_map<int, int> hash;hash[0] = 1;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;}

矩阵区域和

1314. 矩阵区域和 - 力扣(LeetCode)

思路

本题需要二维数组的知识,可使用前面的二维数组模板。

本题题意是选取某一位置,计算其周围一圈数字的和(包括它本身),像这样:

为防止dp表越界问题,我们仍然从1开始计数,所以创建dp数组时,mat[i][j]要变成mat[i-1][j-1].

如图为原数组mat与dp数组的关系,dp数组相当于左边加一列,上面加一行,所以使用mat数组时需要减一。

为了防止选取数字周围发生越界,我们将选取矩阵的左上角与右下角坐标(x1, y1),(x2, y2)的关系了解清楚:

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;

如果是负数就与0比大小,如果太大了就与最大值比大小。

同样地,因为dp数组从1开始计数,所以将mat表中数据需要加一

代码 

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));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];vector<vector<int>> ret(m, vector<int>(n));int x1 = 0, x2 = 0;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.mzph.cn/news/892486.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Git】问题汇总

在push的时候显示 protocol error: bad line length 8192 我在本地创建了一个gogs服务器&#xff0c;现在正在上传代码&#xff0c;但是出现了上述的这个问题。 解决方法 设置本地http.postBuffer&#xff08;待验证&#xff09; 方法一&#xff1a;全局配置 git config --g…

STM32和国民技术(N32)单片机串口中断接收数据及数据解析

一、串口配置 根据单片机不同&#xff0c;串口IO口配置也不同&#xff0c;像STM32单片机&#xff0c;RX脚可以配置为复用输出&#xff0c;也可以配置为浮空输入模式。但是国民技术单片机&#xff08;N32&#xff09;的RX是不能配置为复用输出模式的&#xff0c;这样是收不到数…

3. 【Vue实战--孢子记账--Web 版开发】--登录大模块

从这篇文章开始我们就进入到了孢子记账的前端开发&#xff0c;在本专栏中我默认大家的电脑上都已经配置好了开发环境。下面我们一起开始编写孢子记账的Web版吧。 一、功能 登录大模块功能包括注册、登录和找回密码功能&#xff0c;在本篇文章中我只会展示注册界面的实现&…

【2024年华为OD机试】 (A卷,100分)- 端口合并(Java JS PythonC/C++)

一、问题描述 题目描述 有 M 个端口组 (1 < M < 10)&#xff0c; 每个端口组是长度为 N 的整数数组 (1 < N < 100)&#xff0c; 如果端口组间存在 2 个及以上不同端口相同&#xff0c;则认为这 2 个端口组互相关联&#xff0c;可以合并。 输入描述 第一行输入端…

73.矩阵置零 python

矩阵置零 题目题目描述示例 1&#xff1a;示例 2&#xff1a;提示&#xff1a; 题解思路分析Python 实现代码代码解释提交结果 题目 题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例…

基于华为ENSP的OSPF状态机、工作过程、配置保姆级别详解(2)

本篇技术博文摘要 &#x1f31f; 基于华为enspOSPF状态机、OSPF工作过程、.OSPF基本配置等保姆级别具体详解步骤&#xff1b;精典图示举例说明、注意点及常见报错问题所对应的解决方法 引言 &#x1f4d8; 在这个快速发展的技术时代&#xff0c;与时俱进是每个IT人的必修课。我…

宝塔安装教程,bt怎么安装 linux

Centos安装脚本 yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh 37a09b35 Ubuntu/Deepin安装脚本 wget -O install.sh http://download.bt.cn/install/install-ubuntu_6.0.sh && sudo b…

SOLID原则学习,接口隔离原则

文章目录 1. 定义2. 为什么要遵循接口隔离原则&#xff1f;3. 违反接口隔离原则的例子4. 遵循接口隔离原则的改进5. 总结 1. 定义 接口隔离原则&#xff08;Interface Segregation Principle, ISP&#xff09; 接口隔离原则是面向对象设计中的五大原则&#xff08;SOLID&#…

测试开发之面试宝典

目录 session和cookie的区别 session和cookie的区别 1.session和cookie都是鍵值对应的 2.session和cookie都是服务器生成的&#xff0c;session的ID&#xff0c;即服各器用来识别读取session对象的一把钥匙 3.session是保存在服各器端&#xff0c;而cookie是返回給客戶端的&…

Jenkins-持续集成、交付、构建、部署、测试

Jenkins-持续集成、交付、构建、部署、测试 一: Jenkins 介绍1> Jenkins 概念2> Jenkins 目的3> Jenkins 特性4> Jenkins 作用 二&#xff1a;Jenkins 版本三&#xff1a;DevOps流程简述1> 持续集成&#xff08;Continuous Integration&#xff0c;CI&#xff0…

SQL进阶实战技巧:统计相同时刻多地登陆的用户?

目录 0 问题描述 1 数据准备 2 代码实现 3 问题拓展 3.1 查询每个用户登录日期的最大空档期

BurpSuite之FUZZ模糊测试

Fuzz会生成大量的随机数据对目标网站进行测试,去挖掘可能存在的漏洞,类似密码爆破,但是fuzz针对的是漏洞进行爆破,它也有自己的爆破字典 (fuzz用的好漏洞少不了) 哪些网站要用fuzz呢? 1. 当最目标网站没有更好的办法的时候就可以使用fuzz尝试爆破测试。 2. 目标网站什么都…

从0到机器视觉工程师(六):配置OpenCV和Qt环境

CMake配置OpenCV CMakeLists.txt文件的编写 cmake_minimum_required(VERSION 3.20) project(test_opencv LANGUAGES CXX) #寻找Opencv库 FIND_PACKAGE(OpenCV REQUIRED) include_directories(test_opencv ${OpenCV_INCLUDE_DIRS}) add_executable(test_opencv main.cpp) TARGE…

Vue3框架核心功能点响应式数据reactive、组合式API setup、computed、组件通信、路由导航,状态管理vuex、pinia等的实战示例代码

记录几个Vue3框架核心功能点&#xff0c;例如响应式数据reactive、组合式API setup、computed、组件通信、路由导航&#xff0c;状态管理vuex、pinia……等实战示例代码&#xff1a; 一、响应式数据&#xff08;Reactive Data&#xff09; 创建响应式对象 使用reactive函数创建…

svelte5中使用react组件

在svelet5中导入并使用react组件库 svelte5中使用react组件 svelte5中使用react组件 在svelet5中导入并使用react组件库, 示例项目地址&#xff1a;https://github.com/shenshouer/my-svelte-react 在svelte5中当前还有问题&#xff0c;无法将children传递到react中渲染 使用…

R语言装环境Gcc报错以及scater包的安装

error: ‘timespec_get’ has not been declared in ‘::’ 80 | using ::timespec_get; 在conda 的虚拟环境中升级gcc的版本 conda install -c conda-forge gcc11 gxx11终极方法&#xff0c;在R的最新版本和环境下装啥都能成功&#xff01;&#xff01; 比如beyondcell的方法…

CDA数据分析师一级经典错题知识点总结(3)

1、SEMMA 的基本思想是从样本数据开始&#xff0c;通过统计分析与可视化技术&#xff0c;发现并转换最有价值的预测变量&#xff0c;根据变量进行构建模型&#xff0c;并检验模型的可用性和准确性。【强调探索性】 2、CRISP-DM模型Cross Industry Standard Process of Data Mi…

Flink概念知识讲解之:Restart重启策略配置

Flink概念知识讲解之&#xff1a;Restart重启策略配置 当 Task 发生故障时&#xff0c;Flink 需要重启出错的 Task 以及其他受到影响的 Task &#xff0c;以使得作业恢复到正常执行状态。 Flink 通过重启策略和故障恢复策略来控制 Task 重启&#xff1a;重启策略决定是否可以…

VUE3 VITE项目在 npm 中,关于 Vue 的常用命令有一些基础命令

如果你正在使用 Vite 构建的 Vue 3 项目&#xff0c;并且想要使用相关的 Vue 和 Vite 工具&#xff0c;下面是一些常用的命令和步骤来创建和管理 Vue 项目。 1. 使用 npm create 创建 Vue 3 项目&#xff08;Vite&#xff09; 如果你还没有创建项目&#xff0c;可以使用以下命…

微服务电商平台课程七:前端框架vue

后台商城: https://github.com/macrozheng/mall-admin-web 前台商城:https://github.com/macrozheng/mall-app-web Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编…