1. 程式人生 > 其它 >LeetCode——375. 猜數字大小 II(Java)

LeetCode——375. 猜數字大小 II(Java)

題目描述

題幹:
我們正在玩一個猜數遊戲,遊戲規則如下:
我從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都不是常人所能觸及,日後需要多加練習

如果文章存在問題或者有更好的題解,歡迎在評論區斧正和評論,各自努力,最高處見