464. Can I Win
Description
Tries
第一次尝试,很容易写出下面的solution
public final class SolutionII implements Solution {
private final Map<Integer, Boolean> cache = new HashMap<>();
private final boolean[] usedInteger = new boolean[21];
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
int maxSum = (1 + maxChoosableInteger) * maxChoosableInteger / 2;
// TODO: Missed case 1: 如果<code>desiredTotal <= 0</code>那么player 1啥也不用做,就能赢
if (desiredTotal <= 0) {
return true;
}
// TODO: Missed case 2: 如果超过了<tt>maxSum</tt>, 怎么玩都取不到0,所以是lose
if (desiredTotal > maxSum) {
return false;
}
final boolean res = canIWinHelper(maxChoosableInteger, desiredTotal);
display(usedInteger);
return res;
}
private boolean canIWinHelper(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= 0) {
return false;
}
// TODO: Missed Case 3: 这里会出现这样的情况,比如剩下desiredTotal = 13, 可以是用了 `4+9=13`, 也可以是用了`5+8=13`
if (cache.containsKey(desiredTotal)) {
return cache.get(desiredTotal);
}
boolean canIWin = false;
for (int i = 1; i <= maxChoosableInteger; i++) {
if (usedInteger[i]) continue;
usedInteger[i] = true;
if (!canIWinHelper(maxChoosableInteger, desiredTotal - i)) {
System.out.println("Return true = " + i);
canIWin = true;
// TODO: Missed Case 4: 这里应该是返回之前应该要unset usedInteger[i]
break;
}
usedInteger[i] = false;
}
cache.put(desiredTotal, canIWin);
return canIWin;
}
}
总共有4个Miss case:
- Missed case 1: 如果
desiredTotal <= 0
那么player 1啥也不用做,就能赢 - 如果超过了
maxSum
, 怎么玩都取不到0,所以是lose - 这里会出现这样的情况,比如剩下desiredTotal = 13, 可以是用了
4+9=13
, 也可以是用了5+8=13
,所以用getState()
- 这里应该是返回之前应该要unset
usedInteger[i]
Correct Solution
priclass Solution {
private final Map<Integer, Boolean> cache = new HashMap<>();
private final boolean[] usedInteger = new boolean[21];
public boolean canIWin(int maxChoosableInteger, int desiredTotal) {
int maxSum = (1 + maxChoosableInteger) * maxChoosableInteger / 2;
if (desiredTotal <= 0) {
return true;
}
if (desiredTotal > maxSum) {
return false;
}
return canIWinHelper(maxChoosableInteger, desiredTotal);
}
private boolean canIWinHelper(int maxChoosableInteger, int desiredTotal) {
if (desiredTotal <= 0) {
return false;
}
// Remind: the reason we don't use desiredTotal is that, it doesn't represent the visited the right status
final int desiredState = getState();
if (cache.containsKey(desiredState)) {
return cache.get(desiredState);
}
boolean canIWin = false;
for (int i = 1; i <= maxChoosableInteger; i++) {
if (usedInteger[i]) continue;
usedInteger[i] = true;
if (!canIWinHelper(maxChoosableInteger, desiredTotal - i)) {
canIWin = true;
usedInteger[i] = false;
break;
}
usedInteger[i] = false;
}
cache.put(desiredState, canIWin);
return canIWin;
}
private int getState() {
int res = 0;
for (int i = 1; i < usedInteger.length; i++) {
res <<= 1;
res |= usedInteger[i] ? 1 : 0;
}
return res;
}
}