前言
最近看了下《算法圖解》確實給本身很多啓發,感受本身看世界都多了一個角度、多了一分透徹,就連玩遊戲的時候也是如此。不過書中的代碼示例都是用python來實現的,而本人是以java爲主攻方向。因此,就閱讀體驗上來說,未免讓我有些不快。爲此,我特地將書中的python代碼都一一翻譯成了Java代碼。連接以下:java
肝了幾萬字,送給看了《算法圖解》倒是主攻Java的你和我(上篇)
肝了幾萬字,送給看了《算法圖解》倒是主攻Java的你和我(下篇)
python
言歸正傳
下面開始描述問題:算法
本人平時比較喜歡玩王者榮耀,最近玩韓信比較多,就想買一個韓信街頭霸王的皮膚。數組
可是在購買點券的過程當中發現這樣一個問題url
我居然不可以爲所欲爲的購買點券數量,只能按照騰訊規定的數量購買點券。這應該是騰訊爲了刺激用戶消費所設置的規則。畢竟本身去湊點券數量也不太好計算,嫌麻煩的用戶可能就會直接購買超量的點券。可是這個時候我忽然就想挑戰一波,拒絕超量消費(實際上是窮 )。因而闡述問題試圖求解:
spa
若是我想買一個韓信街頭霸王的皮膚,已知皮膚的價格爲888點券,而我有50點券的優惠卷,餘額爲8點券,也就是說我需 要購買830點券。可是購買點券的數量又不能爲所欲爲,如上圖所示。可是由於最小單位是1元,也就是10點券,因此我確定能夠湊的剛恰好。問:如何花最少的次數恰好買到830點券?.net
貪心算法
這個時候,可能大都會想到兩種算法:動態規劃算法和貪心算法。
這裏容我偷個懶,採用簡單易行的貪心算法。至於動態規劃算法的解法感興趣的小夥伴們能夠本身試試看。至於貪心算法的核心理念,以前的博客也提到過:
翻譯
每一步都採起最優的作法。用專業術語來說就是:每一步都選擇局部最優解,進而但願最終得到一個全局最優解。3d
代碼以下,註釋仍是蠻詳細的:code
import java.util.ArrayList; import java.util.List; import java.util.Scanner; /** * @author guqueyue * @Date 2020/8/24 * 韓信買皮膚問題 **/ public class SkinBuy { // 能夠購買的點券數量 static int[] coupon = {10, 60, 180, 300, 680, 1180, 1980}; public static void main(String[] args) { // 初始化變量,經過減去餘額優惠卷等計算出實際須要購買的點券數量 int money = getMoney(); // 根據貪心算法獲得如何購買的點券集合 List<Integer> buy = getHowBuy(money); // 輸出購買策略 print(buy, money); } /** * 在控制檯打印出購買策略 * @param buy 購買集合 * @param money 實際須要購買的點券數量 */ private static void print(List<Integer> buy, int money) { System.out.println("尊敬的騰訊摳門用戶,您最少須要花 " + buy.size() + " 次才能恰好湊到" + money + "點券"); System.out.print("您只須要這樣購買點券:"); buy.forEach(b -> { // 遍歷點券集合輸出便可 System.out.print(b + " "); }); } /** * 初始化變量,經過減去餘額優惠卷等計算出實際須要購買的點券數量 * @return */ private static int getMoney() { Scanner input = new Scanner(System.in); // 皮膚的價錢 - 888點券 System.out.print("請輸入您要購買皮膚的價格(點券):"); int price = input.nextInt(); // 帳戶餘額 - 8點券 System.out.print("請輸入您的帳戶餘額:"); int banlance = input.nextInt(); // 優惠卷 - 50點券 System.out.print("請輸入您的優惠卷:"); int discount = input.nextInt(); // 實際須要購買的點券 int money = price - banlance - discount; return money; } /** * 根據貪心算法求出購買點券的策略 * @param money 實際須要購買的點券數量 * @return */ private static List<Integer> getHowBuy(int money) { List<Integer> buy = new ArrayList<>(); while (money > 0) { // 找到能夠購買的點券數組中數額最大的可是不超過money點券數 int maxCoupon = maxCoupon(money); money -= maxCoupon; buy.add(maxCoupon); } return buy; } /** * 找到能夠購買的點券數組中數額最大的可是不超過money點券數 * @param money 實際須要購買的點券數量 * @return */ private static int maxCoupon(int money) { // 默認爲10 - 最小點券購買數 int maxCoupon = 10; for (int m : coupon) { // 有序數組才能夠這樣 if (money > m){ maxCoupon = m; } } return maxCoupon; } }
控制檯輸出結果得:
哼哼,完美!通過這麼一番折騰,買皮膚都變得問心無愧了:
升到了貴族6, 還送了一個狄仁傑的皮膚: