1.概念:
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,算法得到的是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择
2.应用:
平时购物找零钱时,为使找回的零钱的硬币数最少,不要求找零钱的所有方案,而是从最大面值的币种开始,按递减的顺序考虑各面额,先尽量用大面值的面额,当不足大面值时才去考虑下一个较小面值,这就是贪心算法
3.存在局部最优问题的体现:
找零钱时,如果零钱面额是【1,5,10】,仿佛没问题
但如果是【1,5,11】,要找钱的金额是15元时
按照贪心算法的思想,从最大金额开始遍历,找钱方案是11+1+1+1+1 = 15,一共五张纸币
但实际情况是,用5 + 5 + 5 = 15的找钱方案才是最优的
猜测是因为10不是质数的原因,具体原因未知
用动态规划则没有这个问题
4.代码
import java.util.*;
class Main{
public static int tanxin(int[] coins, int sum){
Arrays.sort(coins);
int ans = 0;
for(int i = coins.length - 1; i >= 0; i--){
if(sum >= coins[i]){
int num = sum/coins[i];
sum = sum - num * coins[i];
ans += num;
System.out.println("换" + coins[i] + "元零钱" + num + "张");
if(sum == 0){
break;
}
}
}
return ans;
}
public static int dynamicPlan(int[] coins, int sum){
Arrays.sort(coins);
int[] dp = new int[sum + 1];
Arrays.fill(dp,sum + 1);//要赋初值
dp[0] = 0;
for(int i = 1; i < dp.length; i++){
for(int j = 0; j < coins.length; j++){
if(i - coins[j] >= 0){
dp[i] = Math.min(dp[i], dp[i - coins[j]] + 1);
}
}
}
return dp[sum];
}
public static void main(String[] args){
int[] coins = {1,5,10};
int[] coins1 = {1,5,11};
int sum = 15;
System.out.println("使用贪心算法,最终换零钱张数为:" + tanxin(coins1,sum));//存在局部最优问题
System.out.println("使用动态规划算法,最终换零钱张数为:" + dynamicPlan(coins1,sum));
}
}