LeetCode——375. 猜數字大小 II(Java)
阿新 • • 發佈:2021-11-12
題目描述
題幹: 我們正在玩一個猜數遊戲,遊戲規則如下: 我從1到 n 之間選擇一個數字,你來猜我選了哪個數字。 每次你猜錯了,我都會告訴你,我選的數字比你的大了或者小了。 然而,當你猜了數字 x 並且猜錯了的時候,你需要支付金額為 x 的現金。 直到你猜到我選的數字,你才算贏得了這個遊戲。 示例: n = 10, 我選擇了8. 第一輪: 你猜我選擇的數字是5,我會告訴你,我的數字更大一些,然後你需要支付5塊。 第二輪: 你猜是7,我告訴你,我的數字更大一些,你支付7塊。 第三輪: 你猜是9,我告訴你,我的數字更小一些,你支付9塊。 遊戲結束。8 就是我選的數字。 你最終要支付 5 + 7 + 9 = 21 塊錢。 給定n ≥ 1,計算你至少需要擁有多少現金才能確保你能贏得這個遊戲。
題解思路
返回確保可以完成所有遊戲的最少金額,這裡就需要從少的數字開始模擬
如果只有一個數字,那就返回0,如果兩個數字,我們需要返回較大的數字
如果有三個數字,我們就需要先選擇一個數字,然後外加兩邊和較大的一側繼續處理
到這裡我們就確定可以用動態規劃的思路來解決了,這裡肯定還有人想問為什麼不用二分呢
二分的話就不能確保贏或者至少玩完整的情況了,我們用dp二維陣列來限制數字左右範圍來計算
正確程式碼
public int getMoneyAmount(int n) { int[][] dp = new int[n + 1][n + 1]; // 範圍是從1到n return dfs(dp, 1, n); } private int dfs(int[][] dp, int left, int right) { // 只有一個數字的情況 if (left >= right) return 0; // 防止重複計算 if (dp[left][right] != 0) return dp[left][right]; int res = Integer.MAX_VALUE; // 遞迴得到保證可以玩完整的情況 for (int i = left; i <= right; i++) { int cost = i + Math.max(dfs(dp, left, i - 1), dfs(dp, i + 1, right)); res = Math.min(res, cost); } dp[left][right] = res; return res; }
總結
這裡用樹的模型來解決問題,所以用深度優先遍歷的寫法模擬出每種情況
說到底我看了解析和視訊也沒怎麼徹底搞懂,果然dp都不是常人所能觸及,日後需要多加練習
如果文章存在問題或者有更好的題解,歡迎在評論區斧正和評論,各自努力,最高處見