一道经典贪心、动态规划题。
题目描述:给你一个整数数组 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、贪心;2、动态规划
一、贪心
话不多说上代码:
// 贪心
public static int maxSubArray(int[] nums) {
int ans = Integer.MIN_VALUE;
int max = 0;
for (int i = 0; i < nums.length; i++) {
if(max > 0){
// 不断
max += nums[i]; // 加上当前数
ans = Math.max(ans,max);
}else {
// 断
max = nums[i]; // 当前数作为新的开头
ans = Math.max(ans,max);
}
}
return ans;
}
我们要找的是一段连续子串,刚开始时候,将第一个元素作为首元素,添加到我们的“队列”中,此时,第一个元素就是我们的这个队列的“和”(因为我们只有一个元素),然后遍历到第二个元素,此时我们需要判断“前队列”的和是否大于0,为什么呢,如果“前队列”的和是小于0的,那么“前队列”对于我们后面要计算的队列就是累赘,我们需要“斩断”这个累赘序列,以现在所在的位置的元素为“新队列”的首元素,再向下遍历,用一个“ans”变量来接过往队列的和的最大值,就是我们最后所需要的。
二、动态规划
话不多说上代码:
// 动态规划
public static int maxSubArray(int[] nums){
int[] dp = new int[nums.length];
dp[0] = nums[0];
for (int i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i - 1] + nums[i],nums[i]);
}
Arrays.sort(dp);
return dp[nums.length - 1];
}
动态规划,其实和贪心有相似之处,详细的dp(即动态规划)算法学习还需要去找其他资源,这里只提供解题方法。
我们创建dp数组,其中 dp[i] 代表的是以索引为i处的元素结尾的队列的元素和的最大值。由于0是第一位,所以dp[0]的值即为索引为0的元素的值。然后我们开始遍历,从 1 开始,我们将以前一个元素结尾的队列的最大和与当前元素相加,再和当前元素值之间取较大值,即为以当前元素结尾的队列和的最大值。最后将dp数组排序,取最大值即为我们所需要的结果。