[leetcode] 464. Can I Win (Medium)
阿新 • • 發佈:2018-11-11
兩個人依次從1~maxNum中選取數字(不可重複選取同一個),累和。當一方選取數字累和後結果大於等於給定的目標數字,則此人勝利。
題目給一個maxNum和targetNum,要求判斷先手能否勝利。
思路:
首先判斷兩種特殊條件:
- 可選最大值大於等於目標值,直接返回true。
- 其中一個人可選的最大值小於目標值,直接返回false。
具體再看題目,題目給出maxNum不大於20,則可狀態壓縮為一個int(32位)來儲存每個數字是否被使用過(題解中利用1-32位進行儲存)。
利用一個map儲存選取每一個數字的情況,每一次選擇前進行判斷,如若已經有過選取該數字的情況,則返回map裡的值。
遍歷i從1到maxN,考慮選取i的情況:
判斷先手勝利條件:
- 選上i數字後,大於等於目標值可勝利。
( i >= targetN )
- 選上i數字後,後手輸了。
( helper(maxN, targetN - i, mask | visited) == false) )
返回true。
其他情況下,則表示先手輸,返回false。
Runtime: 137 ms, faster than 43.48% of Java
class Solution { public Map<Integer, Boolean> m = new HashMap<Integer, Boolean>(); public boolean helper(int maxN, int targetN, int visited) { if (m.containsKey(visited)) return m.get(visited); for (int i = 1; i <= maxN; i++) { int mask = (1 << i); if ((mask & visited) == 0 && (i >= targetN || helper(maxN, targetN - i, mask | visited) == false)) { m.put(visited, true); return true; } } m.put(visited, false); return false; } public boolean canIWin(int maxChoosableInteger, int desiredTotal) { if (maxChoosableInteger >= desiredTotal) return true; if ((1 + maxChoosableInteger) * maxChoosableInteger / 2 < desiredTotal) return false; return helper(maxChoosableInteger, desiredTotal, 0); } }