携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第19天,点击查看活动详情
题目:Leecode 【难易度:中等】
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [5,4,-1,7,8]
输出:23
提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
解题思路
题目需求是 找出一个具有最大和的连续子数组,返回最大和。到现在做了这么多的动态规划算法的题,就很自然想到用动态规划来解。
按照动态规划流程来解:
- 确定一个动态连续子数组dp,题目意思是子数组中至少有1个元素。
做多了动规的题,其实很快就会判断出:dp[i]就是以 nums[i] 结尾的子序列的最大和。想到了这一点,那其实就比较简单了,所求的最大值= max(dp[0], dp[1],...,dp[n-1])。就是找出哪个连续子序列和值最大
- 找出数组dp元素键的递推关系
dp[i]有两个方向可以推出来:
- dp[i - 1] + nums[i],即:nums[i]加入当前连续子序列和
- nums[i],即:从头开始计算当前连续子序列和
取两者中值更大的,所以dp[i] = max(dp[i - 1] + nums[i], nums[i]);
- 确定初始值
这里确定初始值还是很简单的,只有一个元素就出来了:dp[0] = nums[0]
代码分析
// 该题的程序代码
public int maxSubArray(int[] nums) {
int len = nums.length;
int [] dp = new int[len]; // 定义动态数组dp
dp[0] = nums[0]; // 确定初始值
int max = dp[0];
for (int i = 1; i < len; i++){
// 获取更大值
dp[i] = (dp[i-1]+nums[i] > nums[i]) ? dp[i-1] + nums[i] : nums[i];
if (dp[i] > max) {
max = dp[i];
}
}
return max;
}
题目中的提示就表明:nums 数组是非空且元素至少有1个,所以上述代码没有做空判断检测处理。
日常开发中,还必须先做参数检查:nums 是null 或 nums.length=0都要做判断处理
public int maxSubArray(int[] nums) {
if(nums == null || nums.length == 0) {// nums 是空 或 nums没有元素
return 0;
}
...
}
实例运行结果:nums = new int[]{-2, 1, -3, 4, -1, 2, 1, -5, 4}
在掘金(JUEJIN) 一起分享知识, Keep Learning!