Welcome to Subscribe On Youtube

294. Flip Game II

Description

You are playing a Flip Game with your friend.

You are given a string currentState that contains only '+' and '-'. You and your friend take turns to flip two consecutive "++" into "--". The game ends when a person can no longer make a move, and therefore the other person will be the winner.

Return true if the starting player can guarantee a win, and false otherwise.

 

Example 1:

 Input: currentState = "++++" Output: true Explanation: The starting player can guarantee a win by flipping the middle "++" to become "+--+". 

Example 2:

 Input: currentState = "+" Output: false 

 

Constraints:

  • 1 <= currentState.length <= 60
  • currentState[i] is either '+' or '-'.

 

Follow up: Derive your algorithm's runtime complexity.

Solutions

The function canWin means: “In the current state, there is at least one possible option that can make him/her win”.

  • class Solution { private int n; private Map<Long, Boolean> memo = new HashMap<>(); public boolean canWin(String currentState) { long mask = 0; n = currentState.length(); for (int i = 0; i < n; ++i) { if (currentState.charAt(i) == '+') { mask |= 1 << i; } } return dfs(mask); } private boolean dfs(long mask) { if (memo.containsKey(mask)) { return memo.get(mask); } for (int i = 0; i < n - 1; ++i) { if ((mask & (1 << i)) == 0 || (mask & (1 << (i + 1))) == 0) { continue; } if (dfs(mask ^ (1 << i) ^ (1 << (i + 1)))) { continue; } memo.put(mask, true); return true; } memo.put(mask, false); return false; } } 
  • using ll = long long; class Solution { public: int n; unordered_map<ll, bool> memo; bool canWin(string currentState) { n = currentState.size(); ll mask = 0; for (int i = 0; i < n; ++i) if (currentState[i] == '+') mask |= 1ll << i; return dfs(mask); } bool dfs(ll mask) { if (memo.count(mask)) return memo[mask]; for (int i = 0; i < n - 1; ++i) { if ((mask & (1ll << i)) == 0 || (mask & (1ll << (i + 1))) == 0) continue; if (dfs(mask ^ (1ll << i) ^ (1ll << (i + 1)))) continue; memo[mask] = true; return true; } memo[mask] = false; return false; } }; 
  • class Solution: def canWin(self, s: str) -> bool: for i in range(0, len(s) - 1): if s[i:i + 2] == "++": if not self.canWin(s[:i] + "--" + s[i + 2:]) # Note: after flip, opponent cannot win, then player can win  return True return False #############  class Solution: def canWin(self, s: str) -> bool: for i in range(1, len(s)): if s[i] == '+' and s[i - 1] == '+': if not self.canWin(s[:i - 1] + "--" + s[i + 1:]): # Note: after flip, opponent cannot win, then player can win  return True return False #############  ''' big-O analysis: (N^2) ''' class Solution: def canWin(self, currentState: str) -> bool: @cache def dfs(mask): for i in range(n - 1): if (mask & (1 << i)) == 0 or (mask & (1 << (i + 1)) == 0): continue if dfs(mask ^ (1 << i) ^ (1 << (i + 1))): continue return True return False mask, n = 0, len(currentState) for i, c in enumerate(currentState): if c == '+': mask |= 1 << i return dfs(mask) ############  ''' big-O analysis: (N!) ''' class Solution(object): def canWin(self, s): """ :type s: str :rtype: bool """ def helper(s, visited): if s in visited: return visited[s] visited[s] = False for i in range(0, len(s) - 1): if s[i] + s[i + 1] == "++": if helper(s[:i] + "--" + s[i + 2:], visited) == False: visited[s] = True return visited[s] visited = {} return helper(s, visited) 
  • func canWin(currentState string) bool { n := len(currentState) memo := map[int]bool{} mask := 0 for i, c := range currentState { if c == '+' { mask |= 1 << i } } var dfs func(int) bool dfs = func(mask int) bool { if v, ok := memo[mask]; ok { return v } for i := 0; i < n-1; i++ { if (mask&(1<<i)) == 0 || (mask&(1<<(i+1))) == 0 { continue } if dfs(mask ^ (1 << i) ^ (1 << (i + 1))) { continue } memo[mask] = true return true } memo[mask] = false return false } return dfs(mask) } 

All Problems

All Solutions