《算法题讲解指南:优选算法-前缀和》--31.连续数组,32.矩阵区域和

《算法题讲解指南:优选算法-前缀和》--31.连续数组,32.矩阵区域和

🔥小叶-duck个人主页

❄️个人专栏《Data-Structure-Learning》

《C++入门到进阶&自我学习过程记录》《算法题讲解指南》--从优选到贪心

未择之路,不须回头
已择之路,纵是荆棘遍野,亦作花海遨游


目录

31. 连续数组

题目链接:

题目描述:

题目示例:

解法(前缀和+哈希表):

算法思路:

C++算法代码:

算法总结及流程解析:

32. 矩阵区域和

题目链接:

题目描述:

题目示例:

解法:

算法思路:

C++算法代码:

算法总结及流程解析:

结束语


31. 连续数组

题目链接:

525. 连续数组 - 力扣(LeetCode)

题目描述:

题目示例:

解法(前缀和+哈希表):

算法思路:

      稍微转换一下题目,就会变成我们熟悉的题:

  • 本题让我们找出一段连续的区间,0和1出现的次数相同。
  • 如果将0记为-1,1记为1,问题就变成了找出一段区间,这段区间的和等于0
  • 于是,就和之前做过的那个和为 k 的子数组的题思路类似了

      设 i 为数组中的任意位置,用 sum[i] 表示【0,i】区间内所有元素的和。
      想知道最大的【以 i 结尾的和为 0 的子数组】,就要找到从左往右第一个 x1 使得【x1,i】区间内所有元素的和为 0。那么【0,x1-1】区间内的和是不是就是 sum[ i ] 了。于是问题就变成:

  • 找到在【0,i - 1】区间内,第一次出现 sum[ i ] 的位置即可。

      我们还是不用真的初始化一个前缀和数组,因为我们只关心 i 位置之前,第一个前缀和等于 sum[ i ] 的位置,因此,我们仅需用一个哈希表,一边求当前位置的前缀和,一边记录第一次出现该前缀和的位置。

C++算法代码:

class Solution { public: int findMaxLength(vector<int>& nums) { unordered_map<int, int> hash; int len = 0; int sum = 0; hash[0] = -1; for(int i = 0; i < nums.size(); i++) { if(nums[i] == 0) { nums[i] = -1; } sum += nums[i]; if(hash.count(sum)) { len = max(len, i - hash[sum]); } else //当第一次遇见前缀和则哈希表存放对应的下标(保证长度最短) { //如果是重复遇见相同的前缀和,则只更新长度不存放到哈希表 //因为重复遇见的前缀和长度一定比第一次长,无需存放 hash[sum] = i; } } return len; } };

算法总结及流程解析:

32. 矩阵区域和

题目链接:

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

题目描述:

题目示例:

解法:

算法思路:

      二维前缀和的简单应用题,关键就是我们在填写结果矩阵的时候,要找到原矩阵对于区域的【左上角】以及【右下角】的坐标(大家可以画图,我后面的笔记里会有)

  • 左上角坐标:x1 = i - k,y1 = j - k,但是由于可能会【超过矩阵】的范围,因此需要对 0 取一个 max。因此修正后的坐标为:x1 = max(0, i - k),y1 = max(0, j - k);
  • 右下角坐标:x2 = i + k,y2 = j + k,但是由于可能会【超过矩阵】的范围,因此需要对 m-1,以及 n - 1 取一个 min。因此修正后的坐标为:x2 = min(m-1, i+k),y2 = min(n-1, j+k)。

      然后将求出来的坐标代入到【二维前缀和矩阵】的计算公式上即可(但是要注意下标的映射关系)

C++算法代码:

class Solution { public: vector<vector<int>> matrixBlockSum(vector<vector<int>>& mat, int k) { int m = mat.size(); int n = mat[0].size(); vector<vector<int>> sums(m + 1, vector<int>(n + 1, 0)); vector<vector<int>> ret(m, vector<int>(n, 0)); for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { sums[i + 1][j + 1] = mat[i][j] + sums[i][j + 1] + sums[i + 1][j] - sums[i][j]; } } for(int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { //max和min是为了处理越界情况 ret[i][j] = sums[min(m, i + 1 + k)][min(n, j + 1 + k)] - sums[max(0, i - k)][min(n, j + 1 + k)] - sums[min(m, i + 1 + k)][max(0, j - k)] + sums[max(0, i - k)][max(0, j - k)]; //i + 1和j + 1的目的就是为了和mat进行映射关系,sums[i + 1][j + 1] -> mat[i][j] //然后i - k实际上是i + 1 - k - 1,i + 1依然是与mat进行映射关系 } } return ret; } };

算法总结及流程解析:

结束语

      到此,31.连续数组,32.矩阵区域和 这两道算法题就讲解完了。连续数组 将0/1转换后用前缀和+哈希表寻找和为0的最长子数组;矩阵区域和 通过二维前缀和快速计算矩阵区域和,注意处理边界条件。希望大家能有所收获!

Read more

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

双剑破天门:攻防世界Web题解之独孤九剑心法(十)

免责声明:用户因使用公众号内容而产生的任何行为和后果,由用户自行承担责任。本公众号不承担因用户误解、不当使用等导致的法律责任 **本文以攻防世界部分题为例进行演示,后续会对攻防世界大部分的web题目进行演示,如果你感兴趣请关注** 目录 一:Lottery 二:ics-05 三:总结 一:Lottery 打开后发现这个靶场加载异常缓慢,然后他还给了源码,我们先不看源码先熟悉一下这个网站是什么 这应该是一个类似猜数字游戏,选对7个号码即可得到相应奖励 然后注册 随便输入7个数字发现一个也没中,白费2元 然后我们随便点击这个网站的功能发现如果想要flag需要有相对应的余额 我们这会的思路就是利用bp抓包看看能不能修改我们的余额 好像成功了,我们试一试能不能换flag 居然说没有足够的钱,这个方法不行只要将页面上的数字修改只要刷新就会变回原来的余额 居然不能修改余额那就看看在猜数字的页面有没有突破口,发现其访问了api.php我们继续代码审计 看到如下核心代码,首先随机生成七位数字(random_win_nums)然后将其赋值给$win_number。随后关

By Ne0inhk
基于C++11手撸前端Promise

基于C++11手撸前端Promise

文章导航 * 引言 * 前端Promise的应用与优势 * 常见应用场景 * 并发请求 * Promise 解决的问题 * 手写 C++ Promise 实现 * 类结构与成员变量 * 构造函数 * resolve 方法 * reject 方法 * then 方法 * onCatch 方法 * 链式调用 * 使用示例 * `std::promise` 与 `CProimse` 对比 * 1. 基础功能对比 * 2. 实现细节对比 * (1) 状态管理 * (2) 回调注册与执行 * (3) 异步支持 * (4) 链式调用 * 3. 代码示例对比 * (1) `CProimse` 示例 * (2) `std::promise` 示例 * 4.

By Ne0inhk
HDFS NameNode高可用(HA)完全指南:原理、组件与实现

HDFS NameNode高可用(HA)完全指南:原理、组件与实现

HDFS NameNode高可用(HA)完全指南:原理、组件与实现 * 引言 * 一、NameNode HA架构总览 * 1.1 架构目标 * 1.2 架构图 * 1.3 核心设计思想 * 二、核心组件详解 * 2.1 组件一览表 * 2.2 JournalNode:共享存储的核心 * 工作原理 * 2.3 ZooKeeper:分布式协调者 * 2.4 ZKFC:故障转移控制器 * 2.5 DataNode的特殊角色 * 三、元数据同步机制:QJM详解 * 3.1 QJM是什么? * 3.2 写入流程 * 3.

By Ne0inhk
LeetCode算法日记 - Day 5: 长度最小的子数组、无重复字符的最长子串

LeetCode算法日记 - Day 5: 长度最小的子数组、无重复字符的最长子串

目录 1. 长度最小的子数组 1.1 题目解析 1.2 解法 1.3 代码实现 2. 无重复字符的最长子串 2.1 题目解析 2.2 解法 2.3 代码实现 1. 长度最小的子数组 209. 长度最小的子数组 - 力扣(LeetCode) 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: 输入:

By Ne0inhk