原题链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/
解题思路:局部最优解即为全局最优解(具有最优子结构性质),所以每次出现收益就累加收益,具有贪心选择性质(即所求问题的整体最优解可以通过一系列局部最优的选择--贪心选择来达到)。
class Solution {
public int maxProfit(int[] prices) {
int sum = 0;
for(int i = 1; i < prices.length; i++){
if(prices[i] > prices[i - 1]){
sum += prices[i] - prices[i-1];
}
}
return sum;
}
}
背包问题也能有贪心算法求解,但0-1背包问题只能用动态规划,因为用贪心无法保证最终能将背包装满。
贪心算法解背包问题的基本步骤:
•1)计算每种物品单位重量的价值Vi / Wi,并从高到低排序。
•2)依贪心选择策略:将尽可能多的单位重量价值最高的物品装入背包。
•3)若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。
•4)依此策略一直进行下去,直到背包装满为止。
证明:
还有活动安排问题,求解思路:先按活动结束时间的非降序排列:f1<=f2<=...fn.
void GreedySelector(int n,Type s[],Type f[],bool A[]){
A[1]=true;
int j=1;
for(int i=2;i<=n;i++){
if(s[i]>=f[j]){A[i]=true;j=i;}
else A[i]=false;
}
证明:活动安排有一个最优解以贪心选择开始即该最优解中包含活动1.
设E={1,2....,n}是所给的活动集合,已按结束时间非减的顺序排列,设A包含于E是该问题的一个最优解,且A中活动也按活动时间非减序排列,A中第一个活动是k。若k=1,则A就是一个以贪心选择开始的最优解,若k>1,则设B=A-{k}∪{1}。因为f1<=fk,且A中活动相容,故B中活动也相容。又B中活动个数与A中活动个数相同,且A是最优的,所以B也是最优的。B是以贪心活动1开始的最优活动安排。证得总存在以贪心选择开始的最优活动安排方案。(其实当k>1时证明思路就是寻求一个以活动1开始的安排B与A等价)
做了贪心选择,即选了活动1后,原问题简化成了A' =A-{1}。每一步做的贪心选择都将问题简化为一个更小的与原问题具有相同形式的子问题。对贪心选择次数用数学归纳法可知,贪心算法最终产生原问题的最优解。
还有最优装载问题则是采用重量最轻者先装的贪心选择策略。贪心算法很好用,但证明不易。在可以接受近似解的时候可以优先考虑用贪心。