Leetcode#53.Maximum Subarray(最大子序和)
题目描述
给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。
例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],
连续子序列 [4,-1,2,1] 的和最大,为 6。
扩展练习:
若你已实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
思路
思路一:
maxSum 必然是以nums[i](取值范围为nums[0] ~ nums[n-1])结尾的某段构成的,也就是说maxSum的candidate必然是以nums[i]结果的。如果遍历每个candidate,然后进行比较,那么就能找到最大的maxSum了。
假设把nums[i]之前的连续段叫做sum。可以很容易想到:
- 如果sum>=0,就可以和nums[i]拼接在一起构成新的sum。因为不管nums[i]多大,加上一个正数总会更大,这样形成一个新的candidate。
- 反之,如果sum<0,就没必要和nums[i]拼接在一起了。因为不管nums[i]多小,加上一个负数总会更小。此时由于题目要求数组连续,所以没法保留原sum,所以只能让sum等于从nums[i]开始的新的一段数了,这一段数字形成新的candidate。
- 如果每次得到新的candidate都和全局的maxSum进行比较,那么必然能找到最大的max sum subarray.
在循环过程中,用maxSum记录历史最大的值。从nums[0]到nums[n-1]一步一步地进行。
思路二:
遍历array,对于每一个数字,我们判断,(之前的sum + 这个数字) 和 (这个数字) 比大小,如果(这个数字)自己就比 (之前的sum + 这个数字) 大的话,那么说明不需要再继续加了,直接从这个数字,开始继续,因为它自己已经比之前的sum都大了。
反过来,如果 (之前的sum + 这个数字)大于 (这个数字)就继续加下去。
利用动态规划做题。
只遍历数组一遍,当从头到尾部遍历数组A, 遇到一个数有两种选择 (1)加入之前subArray (2)自己另起一个subArray
设状态S[i], 表示以A[i]结尾的最大连续子序列和,状态转移方程如下:
S[i] = max(S[i-1] + A[i],A[i])
从状态转移方程上S[i]只与S[i-1]有关,与其他都无关,因此可以用一个变量来记住前一个的最大连续数组和就可以了。这样就可以节省空间了。
代码实现
package Array;
/**
* 53.Maximum Subarray(最大子序和)
* 给定一个序列(至少含有 1 个数),从该序列中寻找一个连续的子序列,使得子序列的和最大。
* 例如,给定序列 [-2,1,-3,4,-1,2,1,-5,4],
* 连续子序列 [4,-1,2,1] 的和最大,为 6。
*/
public class Solution53 {
public static void main(String[] args) {
Solution53 solution53 = new Solution53();
int[] arr = {-2, 1, -3, 4, -1, 2, 1, -5, 4};
System.out.println(solution53.maxSubArray(arr));
}
/**
* maxSum 必然是以nums[i](取值范围为nums[0] ~ nums[n-1])结尾的某段构成的,也就是说maxSum的candidate必然是以nums[i]结果的。如果遍历每个candidate,然后进行比较,那么就能找到最大的maxSum了。
* 假设把nums[i]之前的连续段叫做sum。可以很容易想到:
* 1. 如果sum>=0,就可以和nums[i]拼接在一起构成新的sum。因为不管nums[i]多大,加上一个正数总会更大,这样形成一个新的candidate。
* 2. 反之,如果sum<0,就没必要和nums[i]拼接在一起了。因为不管nums[i]多小,加上一个负数总会更小。此时由于题目要求数组连续,所以没法保留原sum,所以只能让sum等于从nums[i]开始的新的一段数了,这一段数字形成新的candidate。
* 3. 如果每次得到新的candidate都和全局的maxSum进行比较,那么必然能找到最大的max sum subarray.
* 在循环过程中,用maxSum记录历史最大的值。从nums[0]到nums[n-1]一步一步地进行。
*
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
int sum = 0; //或者初始化为 sum = INT_MIN 也OK。
int maxSum = nums[0];
for (int i = 0; i < nums.length; i++) {
if (sum >= 0) {
sum += nums[i];
} else {
sum = nums[i];
}
if (sum > maxSum) {
maxSum = sum;
}
}
return maxSum;
}
/**
* 遍历array,对于每一个数字,我们判断,(之前的sum + 这个数字) 和 (这个数字) 比大小,如果(这个数字)自己就比 (之前的sum + 这个数字) 大的话,那么说明不需要再继续加了,直接从这个数字,开始继续,因为它自己已经比之前的sum都大了。
* 反过来,如果 (之前的sum + 这个数字)大于 (这个数字)就继续加下去。
* 利用动态规划做题。
* 只遍历数组一遍,当从头到尾部遍历数组A, 遇到一个数有两种选择 (1)加入之前subArray (2)自己另起一个subArray
* 设状态S[i], 表示以A[i]结尾的最大连续子序列和,状态转移方程如下:
* S[i] = max(S[i-1] + A[i],A[i])
* 从状态转移方程上S[i]只与S[i-1]有关,与其他都无关,因此可以用一个变量来记住前一个的最大连续数组和就可以了。
* 这样就可以节省空间了。
* 时间复杂度:O(n) 空间复杂度:O(1)
*/
public int maxSubArray_2(int[] nums) {
int sum = 0; //或者初始化为 sum = INT_MIN 也OK。
int maxSum = nums[0];
//动态规划
for (int i = 0; i < nums.length; i++) {
sum = Math.max(sum + nums[i], nums[i]);
maxSum = Math.max(sum, maxSum);
}
return maxSum;
}
}
Leetcode#53.Maximum Subarray(最大子序和)的更多相关文章
- LeetCode 53. Maximum Subarray最大子序和 (C++)
题目: Given an integer array nums, find the contiguous subarray (containing at least one number) which ...
- 【LeetCode】53. Maximum Subarray 最大子序和 解题报告(Python & C++ & Java)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 暴力解法 动态规划 日期 题目地址: https:/ ...
- [LeetCode] 53. Maximum Subarray 最大子数组
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- [leetcode]53. Maximum Subarray最大子数组和
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- 53. Maximum Subarray最大子序和
网址:https://leetcode.com/problems/maximum-subarray/submissions/ 很简单的动态规划 我们可以把 dp[i] 表示为index为 i 的位置上 ...
- 【LeetCode】Maximum Subarray(最大子序和)
这道题是LeetCode里的第53道题. 题目描述: 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1 ...
- [LeetCode] 53. Maximum Subarray 最大子数组 --动态规划+分治
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- [array] leetcode - 53. Maximum Subarray - Easy
leetcode - 53. Maximum Subarray - Easy descrition Find the contiguous subarray within an array (cont ...
- 小旭讲解 LeetCode 53. Maximum Subarray 动态规划 分治策略
原题 Given an integer array nums, find the contiguous subarray (containing at least one number) which ...
随机推荐
- Web Deploy 服务器安装设置与使用
一.服务器的安装设置 1.在windows server上确保IIS安装了[管理服务]这个功能.方法是在[服务器管理器]=>[管理]=>[添加角色和功能]=>[下一步]=>[基 ...
- react-native-deprecated-custom-components
速记:从0.44版本开始,Navigator被从react native的核心组件库中剥离到了一个名为react-native-deprecated-custom-components的单独模块中. ...
- jQuery 传递对象参数到Spring Controller
当jQuery 发送ajax请求需要传递多个参数时,如果参数过多,Controller接收参数时就需要定义多个参数,这样接口方法会比较长,也不方便.Spring可以传递对象参数,将你需要的所有查询条件 ...
- linux文件系统启动流程、启动脚本
linux文件系统启动流程.启动脚本 下面是一张Linux启动流程图: 在了解启动流程之前,我们应该先知道系统的几个重要脚本和配置文件,他们对应的路径为: 1. /sbin/init 2. /etc/ ...
- Linux设备树(一 概述)
一 概述 设备树(Device tree)是一套用来描述硬件属相的规则.ARM Linux采用设备树机制源于2011年3月份Linux创始人Linus Torvalds发的一封邮件,在这封邮件中他提倡 ...
- shell脚本[] [[]] -n -z 的含义解析
1.在中括号中,判断变量的值, 加不加双引号的问题?-z 判断 变量的值,是否为空: zero = 0 - 变量的值,为空,返回0,为true- 变量的值,非空,返回1,为false-n 判断变量的值 ...
- centos7.2安装完成的基本操作
系统是centos7.2,安装完成的基本操作 1 修改网卡为eth02 更新系统3 给/etc/rc.local添加执行权限4 添加用户hequan5 禁用selinux6 关闭防火墙安装iptabl ...
- JavaScript时间日期函数
//随机数生成器Math.random() 装换为整数parseInt() 日期时间函数(需要用变量调用):var b = new Date(); //获取当前时间b.getTime() //获取时间 ...
- SqlServer中的事务使用
一.事务的概念和特点 事务(transaction)是恢复和并发控制的基本单位. 事务的特点 原子性:事务是一个工作单元,要都成功,要么的失败 例子:A付款给B,A余额-100,B余额+100,只能都 ...
- windows sqlplus客户端连接oralce数据库中文显示问题
运行环境 服务器:centos6.8 服务器oracle版本:oracle 11g R2 64位,字符集是ZHS32utf8. 客户端:navicat 12x64 windows8.1x64 问题分 ...