每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
来源:互联网 发布:圆周率网络 编辑:程序博客网 时间:2024/06/06 17:01
Maximum Subarray
原题链接Maximum Subarray
在给定数组中找到一个子数组(连续),使这个子数组的和最大。
O(n2)的解法是求sum[i] - sum[j]的最大值,形如sum[i]的式子表示数组[0 : i)的和。这种方法需要i和j都从[0:n)遍历一遍,复杂度比较高。
假设当前找到一个范围[left, right],考虑以下两种情况
- 存在某个[i, left)范围的和大于0,那么[i, right]的和一定大于[left, right]的和
- 存在某个[j, left)范围的和小于0,那么[j, right]的和一定小于[left, right]的和
不过,运算过程中不是先找[left, right]再找i,而是先找[i, left),同时假设[left, right]已存在。也就是说有两种情况
- 如果当前范围的和大于0,那么如果这个范围作为结果范围的一部分,可知会增加结果的大小。是上述第一种情况,继续添加后面的元素即可
- 如果当前范围的和小于0,那么如果这个范围作为结果范围的一部分,可知会减小结果的大小。是上述第二中情况,就需要把当前范围抛弃,从下一位开始重新计算和
当然,在上述遍历的过程中,需要不断判断当前遍历到的子数组的和,更新最大值。
考虑以下问题
- 找到范围[i, left),且范围和为sum1。此时存在i < j < left使[j, left)范围的和sum2 > sum1,那么结果会不会是[j, right]而非[i, right]呢?
- 不会,因为在找[i, left)的过程中是时刻保持[i, left)的和大于0的,当然[i, j)范围的和也会大于0,那么将[i, j)范围添加到结果范围中,是会增加结果的值,所以结果范围仍然是[i, right]
- 找到范围[i, left),且范围和为sum1。此时存在i < j < left使[i, j)范围的和小于0,那么需不需要将[i, j)范围去掉
- 不需要,因为根本不存在这样的j使[i, j)范围的和小于0,原因如第一个问题
代码如下
class Solution {public: int maxSubArray(vector<int>& nums) { if(nums.empty()) return 0; /* sum是当前范围的和,即[i, left)范围的和 */ int sum = 0; /* ans是找到的最大的和 */ int ans = nums[0]; for(int i = 0; i < nums.size(); ++i) { /* 此时sum是大于等于0的,然后将下一个元素添加进范围 */ sum += nums[i]; /* 更新最大值 */ ans = std::max(ans, sum); /* 如果当前范围和(sum)大于0,继续添加下一个,否则,重置为0 */ sum = std::max(sum, 0); } return ans; }};
由于本题要求是O(n)的复杂度,所以只能进行单层for循环,也就是说只能从下标0开始运算,那么每遍历到一个位置都必须考虑以下两个问题
- 是否应该丢弃当前范围的左边界
- 是否应该添加当前遍历到的这个元素
又因为数组元素比较多,每个元素都考虑这两种情况会使复杂度飙升。
本题的解决思路是
- 如果当前找到的范围[i, left)的和是大于0的,那么根本不需要丢弃当前范围的左边界,直接添加遍历到的新元素
- 如果当前找到的范围[i, left)的和是小于0的,那么抛弃已找到的范围,从遍历到的新元素开始重新寻找范围
阅读全文
0 0
- 每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
- [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
- [java实现]找一个数组的最大和的连续子数组(时间复杂度 O(n))
- 求所有子数组的和的最大值。要求时间复杂度为O(n)
- 求子数组的最大和要求O(n)
- 给定一个数组,找出这个和最大的连续子数组的和
- 给定一个二进制数组,找到一个连续的0和1相等的最大子数组。
- LeetCode-连续子数组的最大和
- 给定数组的子数组最大和
- 数组连续子数组的和最大
- 数组连续子数组的最大和
- 题目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个 子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为 O(n)。
- 输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个 子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。
- 题目四:给定一个数组,值可以为正、负和0,请返回累加和小于等于k的最长子数组长度。 时间复杂度:O(n)
- 求一个整型数组的最大和的子数列,要求时间复杂度为线性的
- 求数组的子数组的最大和,时间为O(n)
- 分治法:求给定数组A[1:n]的最大连续子数组
- 求数组的最大子段和,动态规划 时间复杂度O(n)
- 开源TTS(Text To Speah)的选择和使用
- AOJ 0118: Property Distribution (简单DFS)
- 爬虫Scrapy-避免被禁止
- ECharts属性设置
- jsp的include动作和forward动作遇到的问题
- 每天一道LeetCode-----找到给定数组的连续子数组,使这个子数组的和最大,要求复杂度为O(n)
- XGBoost学习笔记
- matlab中关于函数文件和脚本文件使用实例
- 关于linux下的定时
- centos 7 双网卡绑定配置
- Spring Boot 学习笔记(一)
- spring-cloud【Feign】
- Vue.js解析(一)【Vue.js响应式原理】
- Java开发规范