贪心算法总结

优点:简单,高效,省去了为了找最优解可能需要穷举操作,通常作为其它算法的辅助算法来使用;

缺点:不从总体上考虑其它可能情况,每次选取局部最优解,不再进行回溯处理,所以很少情况下得到最优解。

每一步都选取当前状态下最好的选择(局部最优)。(整体不一定是最优解)
助记:贪心即比较贪婪只注重"眼前利益"不能长远考虑

正是因为原问题太复杂无法直接得到全局最优解,所以也无法判定贪心算法得到的结果是否逼近全局最优解,只要最终得到的结果在接受范围内即可

例题案例

注:以下两个案例均不能得到最优解,只能得到近似最优解,案例只是解释思想

1.找零钱问题

假设你开了间小店,不能电子支付,钱柜里的货币只有 25 分、10 分、5 分和 1 分四种硬币,如果你是售货员且要找给客户 41 分钱的硬币,如何安排才能找给客人的钱既正确且硬币的个数又最少?

思路:如果用贪心算法求解

要找给顾客41分且硬币数最少,那么大数值的硬币数越多越好。先用一个25分的,41-25=16。

然后根据局部最优当找零为16时从25,10,5,1中选一个,我们可以选10,16-10=6

找零数为6时从25,10,5,1中选一个,我们可以选5,6-5=1,以此类推

我们可以看到当做出一个选择后,然后相当于以现在的状态为起始状态,再次做出选择

*int* money=41;

int num_25=0,num_10=0,num_5=0,num_1=0;

//不断尝试每一种硬币
while(money>=25) { num_25++; money -=25; }
while(money>=10) { num_10++; money -=10; }
while(money>=5)  { num_5++;  money -=5; }
while(money>=1)  { num_1++;  money -=1; }

//输出结果
cout<< "25分硬币数:"<<num_25<<endl;
cout<< "10分硬币数:"<<num_10<<endl;
cout<< "5分硬币数:"<<num_5<<endl;
cout<< "1分硬币数:"<<num_1<<endl;

/*25分硬币数:1
10分硬币数:1
5分硬币数:1
1分硬币数:1*/

2.01背包问题

有一个背包,最多能承载重量为 C=150的物品,现在有7个物品(物品不能分割成任意大小),编号为 1~7。

重量分别是 wi=[35,30,60,50,40,10,25],价值分别是 pi=[10,40,30,50,35,40,30]。

现在从这 7 个物品中选择一个或多个装入背包,要求在物品总重量不超过 C 的前提下,所装入的物品总价值最高。

思路:若用贪心算法,有3种策略

  1. 价值主导选择,每次都选价值最高的物品放进背包;
  2. 重量主导选择,每次都选择重量最轻的物品放进背包;
  3. 价值密度主导选择,每次选择都选价值/重量最高的(性价比最高的)物品放进背包。

策略1:每次优先选价值最高的

解:按照价值排序则放入背包的编号依次为4、2、6、5。

其价值为50+40+40+35=165,其重量为50+30+10+40=130

策略2:每次优先选重量最轻的

解:按照重量最轻则放入的编号依次为6、7、2、1、5

其价值为40+30+40+10+35=155,其重量为10+25+30+35+40=140

策略3:每次优先选价值/重量最大的

解:这7件物品的价值密度分别为0.286、1.333、0.5、1.0、0.875、4.0、1.2

所以放入的编号依次为6、2、7、4、1

其价值为40+40+30+50+10=170,其重量为10+30+25+50+35=150

LeetCode习题

🚩1.题目1221分割平衡字符串问题

在一个 平衡字符串 中,‘L’ 和 ‘R’ 字符的数量是相同的。给你一个平衡字符串 s,请你将它分割成尽可能多的平衡字符串。

注意:分割得到的每个字符串都必须是平衡字符串。返回可以通过分割得到的平衡字符串的最大数量 。

输入:s = “RLRRLLRLRL”
输出:4
解释:s 可以分割为 “RL”、“RRLL”、“RL”、“RL” ,每个子字符串中都包含相同数量的 ‘L’ 和 ‘R’ 。

解:用变量balance(初始为0)记录扫描到的L和R的数目,遇到L则balance+1否则减1当其为0的时候说明当前找到了平衡子串

上一次划分后balance=0,剩下的平衡子串接着用上述思想(贪心思想)

int balancedStringSplit(string s) {
      int len=s.length();
	    int balance=0,result=0;
	    for (int i = 0; i < len; i++)
	    {
		    if(s[i]=='L')	balance++;
		    if(s[i]=='R')	balance--;
		    if(balance==0)	result++;
	    }
	    return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值