前缀和 差分

差分和前缀和都是算法里边比较重要的知识点,不过学习的难度并不高,这篇文章会讲解相关的内容。

1. 前缀和怎么玩

1)一维前缀和

在该数之前,包括该数的所有数之和,有点类似高中学的数列的前n项和Sn。

2)二维前缀和

根据原数组生成sum数组,sum[i][j]表示从(0, 0)到(i, j)这个范围内的累加和

求法:依次求 左 + 上 - 左上 + 自己,再从左到右,从上到下生成

*往往补第0行、第0列来减少条件判断

【图解】

Q:如果要求某个范围内的累加和怎么办?

设求(a, b)到(c, d)的累加和,则累加和就是

sum[c][d] - sum[a-1][d] - sum[c][b-1] + sum[a-1][b-1]

根据sum数组的定义和下面的图解就非常清晰了

图解如下:

【练习】

有一道模版题,大家可以试着做做:链接

核心的思路就是二维前缀和,我的代码如下: 

class NumMatrix {
public:
    vector<vector<int>> sum;
    NumMatrix(vector<vector<int>>& matrix) {
        int m = matrix.size();
        int n = matrix[0].size();
        sum.resize(m + 1, vector<int>(n + 1));
        
        // 第0行、第0列空出来,减少判断
        for (int a = 0, b = 1; a < m; a++, b++)
            for (int c = 0, d = 1; c < n; c++, d++)
                sum[b][d] = matrix[a][c];
        
        // 求前缀和
        for (int i = 1; i <= m; i++)
            for (int j = 1; j <= n; j++)
                sum[i][j] += sum[i - 1][j] +
                sum[i][j - 1] - sum[i - 1][j - 1];
    }

    int sumRegion(int row1, int col1, int row2, int col2) {
        row2++;
        col2++;
        return sum[row2][col2] - sum[row2][col1]
            - sum[row1][col2] + sum[row1][col1];
    }
};

2. 差分怎么玩

前缀和是为了下面学习差分做铺垫的,那么差分是什么玩意呢?

一般来说,差分分为3种类型,分别是一维差分、二维差分、等差差分

1)一维差分

首先,来看一个例子:

给定一个开始全为0的数组(设大小为8),在指定下标范围进行加减操作,求多次操作后的数组

分别对2~5下标对应的数进行加3,1~3下标加2,4~6下标减2

当然,你也可以每个动作都循环一次,但是那样代码写得有点挫,而差分就是解决这样一类的问题的好方法。

【使用方式】

在每个动作的左位置下标做对应的操作,在右位置的下一个数进行逆操作,所有操作一遍后,用前缀和加工。

这是什么意思,说的是人话吗?🤔

比如,对2~5下标对应的数进行加3,那么就在2位置加3,在6位置减3;(此为一次操作)

对1~3位置加2,就对应着1位置加2,4位置减2;(第二次操作)

对4~6位置减2,对应4位置减2,7位置加2。(第三次操作)

最后进行前缀和加工(此步骤可以在多次操作后进行)

【图解】

【原理】

操作方式就是如上,原理也很简单,因为一开始全是0,那么在进行前缀和操作时就不会受到初始值的影响,只会由我们自己的操作控制。

而在第一个位置加了3,那么经过前缀和的操作就会让该位置及其后的位置都加了3,而因为在最右的位置在往后就不用操作了,那么就需要它的逆操作来抵消了。

【练习】

leetcode_1109航班预订

核心思路就是一维差分 + 前缀和加工,其实就相当于模版题了

参考代码:

class Solution {
public:
    vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {
        vector<int> sum(n + 2, 0);
        for(int i = 0; i < bookings.size(); i++)
        {
            sum[bookings[i][0]] += bookings[i][2];
            sum[bookings[i][1] + 1] -= bookings[i][2];
        }

        vector<int> ans;
        for(int i = 1; i <= n; i++)
        {
            sum[i] += sum[i - 1];
            ans.push_back(sum[i]);
        }
        
        return ans;
    }
};

2)二维差分

跟一维差分类似,也是在初始全为0的条件下,然后在给定两个坐标区间,进行加减操作,多次操作后,求变化后的数组

【使用方式】

设 (a, b) 到 (c, d) 的范围 + v

一次操作:  (a, b) + v 

(a, d+1) - v

(c+1, b) - v

(c+1, d+1) + v

···(多次操作)

最后要加工前缀和

其实原理跟一维差分是类似的,也是因为在前缀和的加工后,对于某个点的变化就成了一片区域的变化,而对于重叠的变化(减了2次)需要再处理

【图解】

【练习】

leetcode_2132贴邮票

核心:二维前缀和与二维差分的结合

思考逻辑:先不考虑邮票的重叠,直接把能贴的位置都贴上,其中判断能不能贴是根据区域前缀和是否为0,贴邮票二维差分的过程(对应四角处理),最后再前缀和加工

注意:此题要非常注意数组的范围,不然会越界

参考代码:链接(内含注释)

3)等差差分

这类问题相当考的较少,可以考虑先跳过

一般的问题描述是,一开始数组全为0,接下来有若干次(已知)操作,每次操作分别是在 l~r 范围上依次加上首项为s,末项为e,公差为d的等差数列,求多次操作后的数组

【使用方式】

arr[l] += s

arr[l + 1] += d - s

arr[r + 1] -= d + e

arr[r + 2] += e

多次操作后,再加工两次前缀和

【图解】

【练习】

luogu_P4231三步必杀

其实就是模板题,思路不难

注意数据量比较大,要用 long long

参考代码:链接

如果有问题可以在评论区一起讨论,对你有帮助的话不妨点个赞👍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/366296.html

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

相关文章

【sentinel流量卫兵搭建与微服务整合】

sentinel流量卫兵搭建与微服务整合 搭建sentinel dashboard控制台微服务整合 搭建sentinel dashboard控制台 1、下载 官网链接 由于官网github网络原因&#xff0c;导致长时间下载失败。 网盘链接 网盘提取码&#xff1a;dwgj 2、运行 将下载jar包放在任意非中文、不包含特殊…

专有云 ABC Stack 联合银联商务打造金融级云平台,入选《2024 央国企上云用云典型案例》

2024 年 1 月&#xff0c;在中国信通院《2024 央国企上云用云典型案例》征集中&#xff0c;百度智能云携手银联商务提交的《银联商务金融级云平台》成功入选「上云用云解决方案典型案例」。 在国家「1 朵央企云统领&#xff0c;N 朵行业云共载&#xff0c;M 朵私有云共生」的央…

jenkins 下载插件sentry-cli失败 证书过期

现状 npm set ENTRYCLI_CDNURLhttps://cdn.npm.taobao.org/dist/sentry-cli npm set sentrycli_cdnurlhttps://cdn.npm.taobao.org/dist/sentry-cli 原因是npm原域名停止解析&#xff0c;在访问上面sentry-cli的cdn资源的时候 证书过期无法下载。 解决&#xff1a; 替换证书过期…

BL808 Linux支持WIFI

BL808芯片介绍 BL808是高度集成的AIoT芯片组&#xff0c;具有Wi-Fi/BT/BLE/Zigbee等无线互联单元&#xff0c;包含多个 CPU 以及音频编码译码器、视频编码译码器和 AI 硬件加速器&#xff0c;适用于各种高性能和低功耗应用领域。 外围接口包括 USB2.0、 Ethernet、 SD/MMC、 …

【python3.8 pre-commit报错】记录pre-commit install报错

一、问题 在执行pre-commit install --allow-missing-config命令时&#xff0c;报错 Traceback (most recent call last):File "C:\ProgramData\Anaconda3\envs\py38\lib\runpy.py", line 192, in _run_module_as_mainreturn _run_code(code, main_globals, None,F…

【Linux】 Linux编译器-gcc/g++使用

&#x1f497;个人主页&#x1f497; ⭐个人专栏——Linux学习⭐ &#x1f4ab;点击关注&#x1f929;一起学习C语言&#x1f4af;&#x1f4ab; 目录 导读1. Linux编译器-gcc/g使用1.1 引入1.2 初识gcc/g1.3 程序运行的四个阶段1.3.1 预处理1.3.2 编译1.3.3 汇编1.3.4 链接 1.…

Git―基本操作

Git ⛅认识 Git⛅安装 GitCentos(7.6)Ubuntu ⛅Git―基本操作创建本地仓库&#x1f342;配置本地仓库&#x1f342;工作区, 暂存区, 版本库&#x1f342;版本库工作区 添加文件&#x1f342;查看文件&#x1f342;修改文件&#x1f342;版本回退&#x1f342;☃️案例 撤销修改…

【Java 数据结构】二叉树

二叉树 1. 树型结构&#xff08;了解&#xff09;1.1 概念1.2 概念&#xff08;重要&#xff09;1.3 树的表示形式&#xff08;了解&#xff09;1.4 树的应用 2. 二叉树&#xff08;重点&#xff09;2.1 概念2.2 两种特殊的二叉树2.3 二叉树的性质2.4 二叉树的存储2.5 二叉树的…

Error: Projects must list all files or use an ‘include‘ pattern.

博主介绍&#xff1a;✌全网粉丝5W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

汽车软件开发模式的5个特点

汽车软件开发属于较为复杂的系统工程&#xff0c;经常让来自不同知识背景的工程师在观点交锋时出现分歧。在解决复杂性和对齐讨论基准时&#xff0c;可以通过勾勒出讨论对象最关键的几个特征来树立典型概念。本文旨在通过5个典型特点的抽取&#xff0c;来勾勒出汽车软件开发模式…

023 for循环详解

什么是for循环 // 练习1 int odd 0; int even 0; for (int i 0; i < 100; i) {if (i % 2 0) {even i;} else {odd i;} } System.out.println("奇数和为:" odd ",偶数和为:" even);// 练习2 for (int i 1; i < 1000; i) {if (i % 5 0) {Sy…

使用STM32 DMA实现高效数据传输的设计与优化

使用STM32的DMA功能可以有效地实现高效的数据传输。在下面的解释中&#xff0c;我将介绍如何设计和优化使用STM32 DMA进行高效数据传输的方法。同时&#xff0c;我将提供一些示例代码来帮助您理解和实践。 ✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术…

决策树的相关知识点

&#x1f4d5;参考&#xff1a;ysu老师课件西瓜书 1.决策树的基本概念 【决策树】&#xff1a;决策树是一种描述对样本数据进行分类的树形结构模型&#xff0c;由节点和有向边组成。其中每个内部节点表示一个属性上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff…

2017年苏州大学837复试机试C/C++

2017年苏州大学复试机试 要求 要求用C/C编程&#xff1b;对程序中必要的地方进行注释。上机规则 请在电脑桌面上新建一个文件夹文件夹名为考试姓名&#xff08;中文&#xff09;&#xff1b;考试完毕后&#xff0c;将所编写的文件放在上述文件中。 第一题&#xff08;20分&…

vue使用antv-x6 绘制流程图DAG图(二)

代码&#xff1a; <template><div class"graph-wrap" click.stop"hideFn"><Toobar :graph"graph"></Toobar><!-- 小地图 --><div id"minimap" class"mini-map-container"></div>…

URL重写

URL重写 URL重写是一种通过修改URL来管理用户会话的会话管理技术。由于URL容易在传输过程中被截取,因此该技术一般在要传输的信息不是很重要时才使用。例如,在线购物门户中,servlet可以修改URL以便包含用户名等用户信息。然后servlet显示该URL。用户单击URL超链接时,信息发…

ES6.8.6 Java客户端发起 增删改查 query (bool)、update、delete

文章目录 环境测试数据增单个新增批量新增 删通过delete by api删除通过delete by query api删除删除索引中指定字段&#xff08;script&#xff09; 改单个修改update by api通过_bulk批量修改批量修改update by query api使用script脚本修改 查完全匹配&#xff08;term&…

【Qt基本功修炼】Qt线程的两种运行模式

1. 前言 QThread是Qt中的线程类&#xff0c;用于实现多线程运行。 QThread有两种工作模式&#xff0c;即 消息循环模式无消息循环模式 两种模式分别适用于不同的场景。下面我们将从多个方面&#xff0c;讲解QThread两种工作模式的区别。 2. 消息循环模式 2.1 实现原理 Q…

nightinage部署

git开源地址 GitHub - ccfos/nightingale: An all-in-one observability solution which aims to combine the advantages of Prometheus and Grafana. It manages alert rules and visualizes metrics, logs, traces in a beautiful web UI. 一、下载源码自己编译运行 二、用…

在本机搭建私有NuGet服务器

写在前面 有时我们不想对外公开源码&#xff0c;同时又想在VisualStudio中通过Nuget包管理器来统一管理这些内部动态库&#xff0c;这时就可以在本地搭建一个NuGet服务器。 操作步骤 1.下载BaGet 这是一个轻量级的NuGet服务器 2.部署BaGet 将下载好的release版本BaGet解…