每天一道leetcode-最大子序和
时间:2022-06-17
本文章向大家介绍每天一道leetcode-最大子序和,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
053_(最大子序和)Maximum Subarray
1 问题描述、输入输出与样例
1.1 问题描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
1.2 输入与输出
输入:
- vector< int>& nums:给定的整数数组 nums
输出:
- int:最大子序和
1.3 样例
1.3.1 样例1
输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
2 思路描述与代码
2.1 思路描述(在线处理法)
其思想是如果当前累加的和 this_sum < 0,那么其肯定不会使得后续的子序和更大,所以累加值 this_sum 置 0 重新累加。
len_nums 为输入数组的长度
max_sum 为记录的最大和
this_sum 记录当前累加的结果
for( i = 0; i < len_nums; i++ ){
this_sum += nums[i];
max_sum = max(max_sum, this_sum);
if(this_sum < 0) this_sum = 0;
}
2.2 代码
class Solution {
public:
const int MIN = -2147483648;
int maxSubArray(vector<int>& nums) {
return maxSubArray_online_processing(nums);
}
//在线处理
int maxSubArray_online_processing(const vector<int>& nums){
int len_nums = nums.size();
int max_sum = MIN;
int this_sum = 0;
for( int i = 0; i < len_nums; i++ ){
this_sum += nums[i];
max_sum = max(max_sum, this_sum);
if(this_sum < 0) this_sum = 0;
}
return max_sum;
}
};
3 思考与拓展
3.1 思考
在线处理的时间复杂度为O(n),此外还有一种方法叫做分治,其空间复杂度为O(nlogn),二者的思想都值得细细回味。
3.1.1 其他方法
3.1.1.1 分治法
分治主要有两个步骤,分和治。 把输入的 nums 数组一分为2,递归求左半部分最大子序和 left_max,递归求右半部分的最大子序和right_max,一遍扫描求跨越中间节点的最大子序和 across_mid_max,三者的最大值即为最大子序和。
class Solution {
public:
const int MIN = -2147483648;
int maxSubArray(vector<int>& nums) {
return maxSubArray_divideAndConquer(nums, 0, nums.size() - 1);
}
int maxSubArray_divideAndConquer(const vector<int>& nums, const int start, const int end){
if(start == end) return nums[start];
int mid = (start + end) / 2;
//获取左、右部分最大值
int left_max = maxSubArray_divideAndConquer(nums, start, mid);
int right_max = maxSubArray_divideAndConquer(nums, mid + 1, end);
//获取中间最大值
int left_across_mid_max = MIN;
int left_across_mid_sum = 0;
for( int i = mid; i >= start; i-- ){
left_across_mid_sum += nums[i];
left_across_mid_max = max(left_across_mid_max, left_across_mid_sum);
}
int right_across_mid_max = MIN;
int right_across_mid_sum = 0;
for( int i = mid + 1; i <= end; i++ ){
right_across_mid_sum += nums[i];
right_across_mid_max = max(right_across_mid_max, right_across_mid_sum);
}
int across_mid_max = left_across_mid_max + right_across_mid_max;
return max(left_max, max(right_max, across_mid_max));
}
};
3.1.2 复杂度分析
方法 |
空间复杂度 |
时间复杂度 |
---|---|---|
在线处理法 |
O(1) |
O(n) |
分治法 |
O(n) |
O(nlogn) |
3.1.3 难点分析
- 在线处理法需要理解如果当前累加的和 this_sum < 0,那么其肯定不会使得后续的子序和更大;
- 分治法需要考虑三种可能的最大子列和情况
3.2 拓展
本题可以有很多变形,可以尝试最小子序列和。
- 【LeetCode 389】 关关的刷题日记30 Find the Difference
- 1708: [Usaco2007 Oct]Money奶牛的硬币
- 1856: [Scoi2010]字符串
- 【LeetCode 409】 关关的刷题日记31Longest Palindrome
- Git的奇技淫巧?
- 3224: Tyvj 1728 普通平衡树
- 【LeetCode 136】 关关的刷题日记32 Single Number
- 1599: [Usaco2008 Oct]笨重的石子
- 【LeetCode 136】 关关的刷题日记33 Intersection of Two
- 1218: [HNOI2003]激光炸弹
- Java多线程高并发学习笔记(一)——Thread&Runnable
- 1257: [CQOI2007]余数之和sum
- 【LeetCode 136】 关关的刷题日记34 Intersection of Two Arrays II
- 1724: [Usaco2006 Nov]Fence Repair 切割木板
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 实战渗透 - 一个怎么够?我全都要!
- 详解 Numpy 中的视图和副本
- 详解 matplotlib 中的两种标注方法
- 混搭 TypeScript + GraphQL + DI + Decorator 风格写 Node.js 应用
- 彻底搞懂闭包,柯里化,手写代码,金九银十不再丢分!
- Kubernetes控制器--副本集ReplicaSet
- Awesome Kubernetes 系列:第一期
- Mongodb多键索引之数组文档
- 在 Cocos Creator 里画个炫酷的雷达图
- 用shader做一个柿子颜色的过场动画
- mysql 找出最新时间的一条数据
- 【NPM库】- 0x05 - 文件、路径操作
- MySQL中insert阻塞问题的分析
- Fedora32下编译安装Qemu5.1并创建ARM版本Linux虚拟机
- 面试官想问的HashMap,都在这一篇里面了!