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

前缀和——从LeetCode题海中总结常见套路

目录

前缀和定义

截断前缀和DP:LeetCode53.最大子序和

经典左右指针:LeetCode209.长度最小的子数组

暴力求解:超时

优雅的双指针写法一:

优雅的双指针写法二:

LeetCode.1588.所有奇数长度子数组的和

手速题:LeetCode.1732.找到最高海拔


 

前缀和定义

对于一个给定的数列 A, 它的前缀和数列S 是通过递推能求出来得部分和,即数列A中某个下标区间内的数的和,可以表示为前缀和相减的形式。                             sum[l,r] = \sum_{i=l}^{r} A[i] = S[r] - S[l-1]    

注:前缀和的定义非常简单,但是其变形的却比较难以把握,其中的精髓思想可以理解为双指针(左右指针),其核心关键词的是差分、累积、动态规划。具体的题目变化多端,其中不乏很多很经典的LeetCode镇店之宝,下面具体来看一看。

截断前缀和DP:LeetCode53.最大子序和

LeetCode DP 绝对经典之一,也是剑指offer里面经典题目之一,不多说了,看注释。

class Solution {
public:int maxSubArray(vector<int>& nums) {int sum = nums[0];int maxnum = nums[0];for (int i = 1; i < nums.size(); i++) {// 前缀和变形,选取前面所有的和或者从当前下标开始的和sum = max(nums[i], sum + nums[i]);// DP思想,动态维护最大的和maxnum = max(maxnum, sum);}return maxnum;}
};

经典左右指针:LeetCode209.长度最小的子数组

暴力求解:超时

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {if (nums.empty())return 0;for (int i = 1; i < nums.size(); i++) nums[i] += nums[i - 1];// for (auto elem : v)//     cout << elem << " ";int ans = nums.size();for (int i = 0; i < nums.size() - 1; i++) {for (int j = i + 1; j < nums.size(); j++) {if ((nums[j] - nums[i]) >= s)ans = min((j - i), ans);}}for (int i = 0; i < nums.size(); i++) {if (nums[i] >= s && i < ans)ans = i + 1;}if (ans == nums.size() && nums[nums.size() - 1] < s)return 0;return ans;}
};

优雅的双指针写法一:

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {if (nums.empty())return 0;int i = 0;int sum = 0, ans = 0;for (int j = 0; j < nums.size(); j++) {sum += nums[j];while (sum >= s) {ans = ans == 0 ? j - i + 1 : min(ans, j - i + 1);sum -= nums[i++];}}return ans;}
};

优雅的双指针写法二:

class Solution {
public:int minSubArrayLen(int s, vector<int>& nums) {if (nums.empty())return 0;int ans = INT_MAX;int sum = 0, i = 0, j = 0;while (j < nums.size()) {sum += nums[j];while (sum >= s) {ans = min(ans, j - i + 1);sum -= nums[i++];}j++;}return ans == INT_MAX ? 0 : ans;}
};

LeetCode.1588.所有奇数长度子数组的和

class Solution {
public:int sumOddLengthSubarrays(vector<int>& arr) {// 前缀和int ans = 0;int length = arr.size();int prefix[length + 1];for (int i = 0; i < length; i++) {prefix[i+1] = prefix[i] + arr[i];}// 每次间隔两个向前取前缀和保证都是奇数数组for (int i = 0; i < length; i++) {for (int j = i; j >= 0; j-=2) {ans += (prefix[i+1] - prefix[j]);}}return ans;}
};

手速题:LeetCode.1732.找到最高海拔

class Solution {
public:int largestAltitude(vector<int>& gain) {// 前缀和,然后找到最大值点int ans = gain[0];for (int i = 1; i < gain.size(); i++) {gain[i] += gain[i - 1];ans = max(ans, gain[i]);}// 因为从海拔为0的点开始的,所以不可能是负数if (ans < 0) {return 0;}return ans;}
};


http://www.mrgr.cn/news/42342.html

相关文章:

  • Python 循环跳出模式
  • WarehouseController
  • CSS3--美开二度
  • 被字节恶心到了
  • 【分布式微服务云原生】深入探索Redis Cluster:打造高效、可扩展的数据集群
  • 《三体》中的“咒语”的 Python实现
  • 基于Springboot+Vue的饮食营养管理信息系统(含源码数据库)
  • Linux之实战命令25:xargs应用实例(五十九)
  • Linux编辑器Vim与Nano之全面比较
  • Java第二阶段---10方法带参---第三节 面向对象和面向过程的区别
  • C语言基础(7)之操作符(1)(详解)
  • LeetCode题练习与总结:丢失的数字--268
  • 习题5 循环
  • 如何让70B参数的大型语言模型在资源有限的边缘设备上高效运行?
  • C/S模型的简单实现(UDP服务器)、本地套接字(sockaddr_un )的讲解
  • 银河麒麟V10 SP1如何进入救援模式?
  • 骨架屏 (懒加载优化)
  • 1.9 物理层设备
  • 高性能防静电主轴4033 AC-ESD 在线路板切割中的非凡表现
  • Java定时器的使用与实际应用场景