这几年商家为了刺激生产是变着花色的推出各种各样的流动,以某多多为首的经营式电商更是让咱们看到了营销的有限“后劲”。
这不,最近刚赶上双 11,小区便利店的老王头也推出了一项「空酒瓶子换酒」的促销流动,它的规定是这样的。
流动规定
客户购买 X 瓶酒,就能够用 Y 个空酒瓶来兑换一瓶新酒。
提醒:
X 和 Y 的取值如下:
- 1 <= X <= 100
- 2 <= Y <= 100
Y 值不固定,随机抽取。
如果喝掉了酒瓶中的酒,那么酒瓶就会变成空的。
请你计算 最多能喝到多少瓶酒。
示例 1:
输出:X = 9, Y = 3
输入:13
解释:你能够用 3 个空酒瓶兑换 1 瓶酒。所以最多能喝到 9 + 3 + 1 = 13 瓶酒。
示例 2:
输出:X = 15, Y = 4
输入:19
解释:你能够用 4 个空酒瓶兑换 1 瓶酒。所以最多能喝到 15 + 3 + 1 = 19 瓶酒。
示例 3:
输出:X = 5, Y = 5
输入:6
示例 4:
输出:X = 2, Y = 3
输入:2
解题思路
这道题难点有两个:第一,用多少个空瓶换一瓶酒是不固定的(随机的);第二,兑换的酒喝完之后还能持续参加兑换流动。因而要在满足这两个的前提条件下,计算本人最多能喝到几瓶。
可能有些敌人看到了本篇题目之后就晓得了解题思路,没错,咱们本文就是要用「贪婪算法」来计算最终答案。同时这道题也合乎贪婪算法的解题思路,那就是有酒瓶就兑换、能兑换多少就兑换多少。
贪婪算法
贪婪算法(Greedy Algorithm),又称贪心算法,是一种在每一步抉择中都采取在以后状态下最好或最优(即最无利)的抉择,从而心愿导致后果是最好或最优的算法。
贪婪算法在有最优子结构的问题中尤为无效。最优子结构的意思是部分最优解能决定全局最优解。简略地说,问题可能分解成子问题来解决,子问题的最优解能递推到最终问题的最优解。
贪婪算法的实现框架
从问题的初始解登程:
while(能朝给定总指标前进一步)
{
利用可行的决策,求出一个可行解元素;
}
由所有解元素组合成问题的一个可行解。
留神:因为用贪婪算法只能通过解部分最优解的策略来达到全局最优解,因而,肯定要留神判断问题是否适宜采纳贪婪算法策略,找到的解是否肯定是问题的最优解。
接下来咱们就用代码来演示一下贪婪算法的具体实现。
代码实现 1:贪婪
首先咱们先把全局问题转换成部分问题:当空瓶子能换一瓶酒的时候,咱们就换一瓶酒,实现代码如下:
// 贪婪 1:用 + 和 - 实现
class Solution {public int numWaterBottles(int numBottles, int numExchange) {
// 最大酒瓶数
int total = numBottles;
// 有酒瓶就兑换
while (numBottles >= numExchange) {
// 执行一轮兑换
numBottles -= numExchange;
++total;
// 兑换一次多一个酒瓶
++numBottles;
}
return total;
}
}
代码解析
实现思路:
- 先把所有酒喝掉
int total = numBottles
; - 有足够的空瓶就去换一瓶酒,执行一次
while
循环; - 在循环中,空瓶的数量 +1,能喝到酒的数量 +1;
- 执行下一次循环判断。
咱们将以上代码提交至 LeetCode,执行后果如下:
代码实现 2:贪婪改良
以上的贪婪算法是一瓶酒一瓶酒进行循环兑换的,那咱们可否每次将所有的空瓶子全副兑换完(可兑换的最大值),而后将兑换的酒再喝完,再进行下一次兑换?
答案是必定的,咱们只须要应用取模和取余操作就能够实现了,具体代码如下:
// 贪婪 2:用 / 和 % 实现
class Solution {public int numWaterBottles(int numBottles, int numExchange) {
// 总酒瓶数
int total = numBottles;
// 有酒瓶就兑换
while (numBottles >= numExchange) {
// 最多可兑换的新酒
int n = numBottles / numExchange;
// 累计酒瓶
total += n;
// 残余酒瓶(残余未兑换 + 已兑换喝掉的)
numBottles = numBottles % numExchange + n;
}
return total;
}
}
咱们将以上代码提交至 LeetCode,执行后果如下:
总结
贪婪算法初看感觉很“难”,但具体实现起来却发现很简略。其实「算法」也是一样的,初看这个词感觉很难很高大上,其实它就是解决某个问题的一种思维、一种固定的“套路”而已,也并无神秘可言。
人常说:路虽远行则将至,事尽管难做者必成。“难”和“易”素来都是绝对的,其实从“难”到“易”就是一个逐步开悟、逐步成长的过程。
举荐浏览:
机会来了,字节跳动年前再招万人,咱们该如何应答必问的算法?
暴力递归算法解说