Algorithm - leetcode 292 Nim Game
Dian a title
You and your friends, two people to play with Nim game: a pile of stones on the table, every time you turn removed 1 - 3 stones. Removed the last stone of the person is the winner. As you just get. You are a wise man, every step is the optimal solution. Write a function to determine whether you can win the game, given the number of stones. Input: 4 Output: false Explanation: If the heap has 4 stones, then you will never win; because whether you take away 1 block 2 block or 3 stones, last stone will always be to get your friends go.
Two Dian ideas
1) first attempt to use violence to solve - recursion
class Solution { public boolean canWinNim(int n) { if(n<=0){ return false; } if(n<=3){ return true; } if(!friendCanWinNim(n-1)){ //拿1块 return true; } if(!friendCanWinNim(n-2)){ //拿2块 return true; } if(!friendCanWinNim(n-3)){ //拿3块 return true; } Return to false ; } // friends take, whether friends can win Private Boolean friendCanWinNim ( int n-) { IF (n-<= 0 ) { return to false ; } IF (n-<=. 3 ) { return to true ; } IF (! canWinNim (. 1-n-)) { // get a return to true ; } IF (! canWinNim (2-n-)) { // get the two return to true ; } IF(! canWinNim (. 3-n-)) { // get the three return to true ; } return to false ; } }
2) timeout phenomenon cache intermediate results
class Solution { Map<Integer, Boolean> resultMap =new HashMap<Integer, Boolean>(); //结果 public boolean canWinNim(int n) { if(n<=0){ return false; } if(n<=3){ return true; } if(results[n]!=null){ return results[n]; } boolean result=false; if(!friendCanWinNim(n-1)){ //拿1块 result=true; resultMap.put(n, result);return result; } if(!friendCanWinNim(n-2)){ //拿2块 result=true; resultMap.put(n, result);return result; } if(!friendCanWinNim(n-3)){ //拿3块 result=true; resultMap.put(n, result);return result; } result=false; resultMap.put (n-, Result); return Result; } // friends take, whether friends can win Private Boolean friendCanWinNim ( int n-) { IF (n-<= 0 ) { return to false ; } IF (n-<=. 3 ) { return to true ; } IF (! canWinNim (. 1-n-)) { // get a return to true ; } IF (! canWinNim (2-n-)) { // get the two return to true ; } IF(! canWinNim (. 3-n-)) { // get the three return to true ; } return to false ; } }
3) Recursion too large, stack overflow exception occurs, will change for recursive loop (similar to dynamic programming)
class Solution { Map<Integer, Boolean> resultMap =new HashMap<Integer, Boolean>(); //缓存先手的结果 public boolean canWinNim(int n) { if(n<=0){ return false; } // 初始化 resultMap.put(1, true); resultMap.put(2, true); resultMap.put(3, true); boolean result1, result2, result3; for(int i=4;i<=n;i++){ // 拿1块 result1=resultMap.get(i-1); // 拿2块 result2=resultMap.get(i-2); // 拿3块 result3=resultMap.get(i-3); if(!result1 || !result2 || !result3){ resultMap.put(i, true); }else { resultMap.put(i, false); }
System.out.println(i+" -> "+resultMap.get(i)); } return resultMap.get(n); } }
4) still timeout, (print intermediate results can be found here looked to explain the law T_T others)
class Solution { public Boolean canWinNim ( int n-) { // law title @ 3 + 1 output will return n-% (3 + 1) = 0! ; } }