LeetCode 53:最大子序和(动态规划)
1、输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
2、动态规划分析:
3、复杂度分析:
时间复杂度:O(N)
空间复杂度:O(N),使用了一维数组。
/**
* 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
* 动态规划:确定状态、状态转移方程,初始化状态,进行输出。
* @param nums
* @return
*/
public int maxSubArray(int[] nums) {
if(nums.length ==0){
return 0;
}
//定义状态:dp[i]:以元素 nums[i]为结尾的连续子数组最大和。
int[] dp = new int[nums.length];
//状态初始化:以 nums[0]结尾的连续子数组最大和为nums[0]。
dp[0] = nums[0];
int res = nums[0];
//状态转移方程:
for (int i=1;i<nums.length;i++){
if(dp[i - 1] > 0){
dp[i] = dp[i-1] + nums[i];
}else{
dp[i] = nums[i];
}
res = Math.max(res,dp[i]);
}
//输出:返回dp列表中的最大值,代表全局最大值。
return res;
}
空间优化:避免使用一维数组。
1、复杂度分析:
时间:O(N)
空间:O(1), 使用常数大小的额外空间,避免使用一维数组。
2、分析:
由于 dp[i] 只与 dp[i-1] 和 nums[i] 有关系,因此可以将原数组 nums用作 dp列表,即直接在 nums上修改即可,由于省去 dp列表使用的额外空间,因此空间复杂度从 O(N)降至 O(1) 。
/**
*
* 输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
* 动态规划,避免使用一维数组,空间复杂度为O(1),空间复杂度为:O(N)
* @param nums
* @return
*/
public int maxSubArray2(int[] nums) {
if(nums.length <1){
return 0;
}
int res = nums[0];
// dp[i] 只与 dp[i-1] 和 nums[i] 有关,将原数组nums用作dp数组,在 nums上修改即可
for(int i=1;i<nums.length;i++){
if(nums[i-1] >0){
nums[i] += nums[i-1];
}
res = Math.max(res,nums[i]);
}
return res;
}