贪心算法part1
贪心算法part1
理论基础
什么是贪心?
贪心的本质是选择每一阶段的最优解,从而达到全局最优
举例:有一堆钞票,可以拿走十张,如何达到最大金额?每次拿走最大的钞票
什么时候用贪心?
贪心算法没有固定套路,一般数学证明有以下两种方法
- 数学归纳法
- 反证法
最好用的策略是举反例
贪心有时就是常识性的推导,所以会下意识认为本应该就这么做
贪心一般解题步骤
过于理论化的步骤(理想化,但是做题时不好用)
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
做题时只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了
总结
贪心没有套路,用的是常识性推导加上举反例,比较抽象
455. 分发饼干 - 力扣(LeetCode)
局部最优:大饼干满足大胃口 --> 全局最优
代码如下:
class Solution {
public int findContentChildren(int[] g, int[] s) {
Arrays.sort(g);
Arrays.sort(s);
int index = s.length - 1;
int res = 0;
for(int i = g.length - 1; i >= 0; i--){ //大饼干满足大胃口,遍历胃口数组
if(index >= 0 && s[index] >= g[i]){
index--;
res++;
}
}
return res;
}
}
376. 摆动序列 - 力扣(LeetCode)
自己做的,感觉也是贪心
局部最优在于:根据当前的state,更新res,并对下面的state进行更新
class Solution {
public int wiggleMaxLength(int[] nums) {
int state = -1;
int res = 0;
for(int i = 0; i < nums.length; i++){
if(state == 0){ //现在应该降序了,也就是nums[i] < nums[i - 1]
if(nums[i] < nums[i - 1]){
res++;
state = 1;
}
}else if(state == 1){ //现在应该升序了,也就是nums[i] > nums[i - 1]
if(nums[i] > nums[i - 1]){
res++;
state = 0;
}
}else if(state == -1 && i != 0){
if(nums[i] > nums[i - 1]){
state = 0;
res++;
}else if(nums[i] < nums[i - 1]){
state = 1;
res++;
}
}else if(state == -1 && i == 0){
res++;
}
}
return res;
}
}
53. 最大子数组和 - 力扣(LeetCode)
贪心
-
贪得是哪里:如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方
-
局部最优:当 连续和 为负数的时候直接放弃,从下一个元素重新计算 连续和 ,因为负数只会拖累后面的总和
-
全局最优:连续选取最大 连续和
代码如下:
class Solution {
public int maxSubArray(int[] nums) {
if(nums.length == 1){
return nums[0];
}
int res = Integer.MIN_VALUE;
int sum = 0;
for(int i = 0; i < nums.length; i++){
sum += nums[i];
res = Math.max(res, sum);
if(sum < 0){
sum = 0;
continue;
}
}
return res;
}
}
浙公网安备 33010602011771号