- 题目
/**
- @Author james
- @Date 2019/7/19
- @Description 求最大子序和 -- 动态规划
*/
public class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 0) {
return 0;
}
/**
* 修改int ans = 0;
* 由边际条件:数组只有一个元素的时候,最大子序和就是该元素,而不是0
*/
int ans = nums[0];
/**
* sum -- 总增益值,判断是否重写统计增益的依据
* 1. 如果 sum + [当前值] > [当前值] 证明 sum 的增益还是为正,可以继续添加子序
* 2. 如果 sum + [当前值] <= [当前值] 证明 sum 之前的增益已经无用
* 若原数组:[1, -2, 5, -3, -1, 9, 4, 6]
* 遍历至:[1, -2, 5, -3, -1] 时,计算出sum = 0 => 增益为0,开始下一次遍历
* 遍历至:[1, -2, 5, -3, -1, 9], 判断sum == 0 => 重置 sum = 9,意思是从9开始新的遍历才有意义
* 3. ans 始终记录最大的sum,遍历完成返回即可
*/
int sum = 0;
for (int i = 0; i < nums.length; i++) {
if (sum > 0) { // sum + nums[i] > nums[i]
sum = sum + nums[i];
}
if (sum <= 0) { // sum + nums[i] <= 0
sum = nums[i];
}
ans = Math.max(ans, sum);
}
return ans;
}
- 类似题目
/**
* @Author james
* @Date 2019/7/12
* @Description 买卖股票最佳时机 (只允许一次买入和买出)
*/
public class Solution {
public int maxProfit(int[] prices) {
/**
* 只允许一次买入和买出,即在最低价买入,最高价卖出即可。
* 若没有时间约束[6,4,2,1]
* => 最大利润为5 显然是不与合理的
* => 不能仅仅从价格高低定位最佳时间。
* 于是可以【动态】得找到最大利润maxProfit = 当前值 - 最小值。
* 并且,最小值的判断永远在计算利润之前,就不会发生[6,4,2,1]的错误答案
*/
int maxProfit = 0;
// 用于存放最小值,确保一定被数组的值覆盖,使用Integer的最大值最好
int minVale = Integer.MAX_VALUE;
for (int i = 0; i < prices.length; i++) {
if (prices[i] < minVale) { // 找到最小值
minVale = prices[i];
}
if (prices[i] - minVale > maxProfit) { // (当前值 - 最小值)比最大利润高,则记录下来
maxProfit = prices[i] - minVale;
}
}
return maxProfit;
}
}
- 通用思路
- 使用一个变量记录最值,遍历完整个数组,最值即确定。
- 使用循环遍历 + 前置判断,隐含了时间的约束条件。