任何算法其实只要找到了合理的解释逻辑或者找到了生活中生动的实践,其实都可以很容易的实现,难的算法只是难在不好找到熟悉的处理场景,如果找到了处理场景,其实算法就无难以之分,无非是代码量多少的问题;
贪心算法的核心就是:局部最优解就能推出全局最优解,无需瞻前顾后!如果局部最优推不出全局最优,就无法使用贪心算法,可能就要用动态规划问题;
贪心算法还有一个特点就是:衡量局部最优的标准只有一个,而不是多个条件,这也是为什么不需要瞻前顾后的原因,就像我面前有三张钞票:100、50、20的,只拿一次,怎样面值最大,局部最优就是只拿面值最大的,而不需要考虑拿的钞票面积是否过大,颜色对自己是否有伤害(脱离现实的胡扯,但我想表达的就是局部最优解的衡量标准只有一个)而动态规划就需要瞻前顾后,判断选择了这一步,对整体的影响是否有益。
那如何判断是不是局部最优就能推出全局最优呢?其实大多数情况下,只要你局部最优的思路找不出反例,就可以了,当想到一种局部最优的思路之后,就想办法找反例去测试,(浅尝辄止即可)。
还是开头那句话无论什么算法问题,如果能找到一个熟悉或者生动的处理场景,逻辑就会特别清晰,清晰到易如反掌,只是代码量多少的问题,代码量多只能说明繁琐,不能说明算法难。算法难易的标准等同于找到熟悉的处理场景的难易;
最大子数组和对应:力扣.53题
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组
是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
可以把该问题模拟为:
小明的上贡之路:数组的内容就像贡品的价值,小明每走一步就要判断,如果之前捡拾的贡品是正数,就把当前位置的贡品+之前的贡品一块上交,如果之前贡品是非正数,就只把当前位置贡品上交;上交之前判断是否是已上交贡品的最大值
代码如下:
class Solution {
public int maxSubArray(int[] nums) {
int max = nums[0];
int pre_sum = nums[0];
for (int i = 1; i < nums.length; i++) {
pre_sum = Math.max(pre_sum + nums[i], nums[i]); // 判断上供的方式,是之前攒的+当前位置,还是只上供当前位置的
max = Math.max(max, pre_sum);
}
return max;
}
}
小明每走一步,只需要在这一步判断出哪个是最大的收益,就是局部最优解。