智力題

我能贏(yíng)嗎

輸入:
maxChoosableInteger = 10
desiredTotal = 11
輸出:
false
思路:我們首先來(lái)看如果給定的數(shù)字范圍大于等于目標(biāo)值的話(huà),直接返回true。如果給定的數(shù)字總和小于目標(biāo)值的話(huà),說(shuō)明誰(shuí)也沒(méi)法贏(yíng),返回false。然后我們進(jìn)入遞歸函數(shù),首先我們查找當(dāng)前情況是否在哈希表中存在,有的話(huà)直接返回即可。我們使用一個(gè)整型數(shù)按位來(lái)記錄數(shù)組中的某個(gè)數(shù)字是否使用過(guò),我們遍歷所有數(shù)字,將該數(shù)字對(duì)應(yīng)的mask算出來(lái),如果其和used相與為0的話(huà),說(shuō)明該數(shù)字沒(méi)有使用過(guò),我們看如果此時(shí)的目標(biāo)值小于等于當(dāng)前數(shù)字,說(shuō)明已經(jīng)贏(yíng)了,或者我們調(diào)用遞歸函數(shù),如果返回false,說(shuō)明也是第一個(gè)人贏(yíng)了。為啥呢,因?yàn)楫?dāng)前我們已經(jīng)選過(guò)數(shù)字了,此時(shí)就該對(duì)第二個(gè)人調(diào)用遞歸函數(shù),只有他的結(jié)果是false,我們才能贏(yíng),所以此時(shí)我們標(biāo)記true,返回true。如果遍歷完所有數(shù)字,我們標(biāo)記false,返回false

class Solution {
public:
    bool canIWin(int maxChoosableInteger, int desiredTotal) {
        if (maxChoosableInteger >= desiredTotal) return true;
        if (maxChoosableInteger * (maxChoosableInteger + 1) / 2 < desiredTotal) return false;
        unordered_map<int, bool> m;
        return canWin(maxChoosableInteger, desiredTotal, 0, m);
    }
    bool canWin(int length, int total, int used, unordered_map<int, bool>& m) {
        if (m.count(used)) return m[used];
        for (int i = 0; i < length; ++i) {
            int cur = (1 << i);   //表示將1左移i位,1,2,4,8...
            if ((cur & used) == 0) {
                if (total <= i + 1 || !canWin(length, total - (i + 1), cur | used, m)) {
                    m[used] = true;
                    return true;
                }
            }
        }
        m[used] = false;
        return false;
    }
};

猜數(shù)字大小(https://leetcode-cn.com/problems/guess-number-higher-or-lower-ii/)

從1-n中選一個(gè)數(shù),n = 10, 我選擇了8.
第一輪: 你猜我選擇的數(shù)字是5,我會(huì)告訴你,我的數(shù)字更大一些,然后你需要支付5塊。
第二輪: 你猜是7,我告訴你,我的數(shù)字更大一些,你支付7塊。
第三輪: 你猜是9,我告訴你,我的數(shù)字更小一些,你支付9塊。
游戲結(jié)束。8 就是我選的數(shù)字。
你最終要支付 5 + 7 + 9 = 21 塊錢(qián)。
給定 n ≥ 1,計(jì)算你至少需要擁有多少現(xiàn)金才能確保你能贏(yíng)得這個(gè)游戲。
思路
dp[i][j]表示從[i,j]中猜出正確數(shù)字所需要的最少花費(fèi)金額.(dp[i][i] = 0)
假設(shè)在范圍[i,j]中選擇x, 則選擇x的最少花費(fèi)金額為: max(dp[i][x-1], dp[x+1][j]) + x
用max的原因是我們要計(jì)算最壞反饋情況下的最少花費(fèi)金額(選了x之后, 正確數(shù)字落在花費(fèi)更高的那側(cè))

    初始化為(n+2)*(n+2)數(shù)組的原因: 處理邊界情況更加容易, 例如對(duì)于求解dp[1][n]時(shí)x如果等于1, 需要考慮dp[0][1](0不可能出現(xiàn), dp[0][n]為0)
    而當(dāng)x等于n時(shí), 需要考慮dp[n+1][n+1](n+1也不可能出現(xiàn), dp[n+1][n+1]為0)
    
    如何寫(xiě)出相應(yīng)的代碼更新dp矩陣, 遞推式dp[i][j] = max(max(dp[i][x-1], dp[x+1][j]) + x), x~[i:j], 可以畫(huà)出矩陣圖協(xié)助理解, 可以發(fā)現(xiàn)
    dp[i][x-1]始終在dp[i][j]的左部, dp[x+1][j]始終在dp[i][j]的下部, 所以更新dp矩陣時(shí)i的次序應(yīng)當(dāng)遵循bottom到top的規(guī)則, j則相反, 由于
    i肯定小于等于j, 所以我們只需要遍歷更新矩陣的一半即可(下半矩陣)
  public int getMoneyAmount(int n) {
        int[][] dp = new int[n+2][n+2];
        for(int i = n; i >= 1; --i) {
            for(int j = i; j <= n; ++j) {
                if(i == j)
                    dp[i][j] = 0;
                else {
                    dp[i][j] = Integer.MAX_VALUE;
                    for(int x = i; x <= j; ++x) 
                        dp[i][j] = Math.min(dp[i][j], Math.max(dp[i][x-1], dp[x+1][j]) + x);   //為什么這個(gè)地方最外面是Math.min???
                }
            }
        }
        return dp[1][n];
    }

nim游戲

你和你的朋友,兩個(gè)人一起玩 Nim 游戲:桌子上有一堆石頭,每次你們輪流拿掉 1 - 3 塊石頭。 拿掉最后一塊石頭的人就是獲勝者。你作為先手。
你們是聰明人,每一步都是最優(yōu)解。 編寫(xiě)一個(gè)函數(shù),來(lái)判斷你是否可以在給定石頭數(shù)量的情況下贏(yíng)得游戲。

示例:
輸入: 4
輸出: false
解釋: 如果堆中有 4 塊石頭,那么你永遠(yuǎn)不會(huì)贏(yíng)得比賽;
因?yàn)闊o(wú)論你拿走 1 塊、2 塊 還是 3 塊石頭,最后一塊石頭總是會(huì)被你的朋友拿走。

  bool canWinNim(int n) {
        return n%4==0?false:true;
    }

變態(tài)跳臺(tái)階

一只青蛙一次可以跳上1級(jí)臺(tái)階,也可以跳上2級(jí)……它也可以跳上n級(jí)。求該青蛙跳上一個(gè)n級(jí)的臺(tái)階總共有多少種跳法。

f(1)=1, f(2)=2, f(3)=4, f(4)=8 設(shè)n+1級(jí)f(n+1),有
f(n+1) = f(1) + f(2) + ... + f(n)
f(n+2) = f(1) + f(2) + ... + f(n+1)
f(n+2)= 2f(1) + 2f(2) + ... + 2f(n)
故得f(n+2) = 2f(n+1)

矩形覆蓋

我們可以用 2 * 1 的小矩形橫著或者豎著去覆蓋更大的矩形。請(qǐng)問(wèn)用n個(gè)2 * 1的小矩形無(wú)重疊地覆蓋一個(gè)2*n的大矩形,總共有多少種方法?
f(1) = 1
f(2) = 2
f(n) = f(n-1) + f(n-2)

孩子們的游戲

有n個(gè)數(shù),從0開(kāi)始編號(hào),每次刪除第m個(gè)數(shù),下一輪循環(huán)從m+1開(kāi)始。求最后剩下的數(shù)字是多少
雖然有遞推公式,但是用鏈表模擬更好

public int LastRemaining_Solution(int n, int m) {
        LinkedList<Integer> list = new LinkedList<>();
        for(int i=0;i<n;i++)
            list.add(i);
        int a = 0;
        while(list.size() > 1)
        {
            a = (a+m-1) % list.size();
            list.remove(a);//每次刪除,直到留下最后的那一個(gè)!
        }
        if(list.size() == 1)
            return list.get(0);//數(shù)組只剩下最后的一個(gè)
        return -1;
    }

n!末尾有多少個(gè)0

思路:5!=54321,0的個(gè)數(shù)和5的個(gè)數(shù)相等0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1出現(xiàn)的次數(shù) 輸入一個(gè)整數(shù)n,求從1到n這n個(gè)整數(shù)的十進(jìn)制表示中1出現(xiàn)的次數(shù)。例如輸入12,從1到12這些整數(shù)中包...
    小小的白菜閱讀 1,165評(píng)論 0 0
  • 該組字母是一組常用英語(yǔ)單詞的第二個(gè)字母,你能推算出下一個(gè)字母是什么嗎?N W H O I I ? 答案:前6個(gè)字母...
    博格體閱讀 815評(píng)論 0 0
  • 聽(tīng)說(shuō)做對(duì)5道,智商就有140! 答案在最后面,不要偷看哦 趕快來(lái)挑戰(zhàn)吧! 01、移動(dòng)3個(gè)圓圈, 把左邊的三角形變成...
    9f19d909a006閱讀 9,138評(píng)論 0 5
  • 你會(huì)喜歡哪個(gè)季節(jié) 夏雨洪荒還是冬雪蒼茫 微微星夜燈光,我們會(huì)在一夜又一夜的冬風(fēng)中行走 早晨你會(huì)在溫暖的被窩醒來(lái),睡...
    白糖蛋黃閱讀 581評(píng)論 0 0
  • 我好怕 再見(jiàn)到你 不過(guò)是多掉幾滴眼淚 又或者 無(wú)風(fēng)無(wú)晴
    思路崎嶇閱讀 152評(píng)論 0 0

友情鏈接更多精彩內(nèi)容