Flip Game II
You are playing the following Flip Game with your friend: Given a string that contains only these two characters: + 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.
Write a function to determine if the starting player can guarantee a win.
For example, given s = "++++", return true. The starting player can guarantee a win by flipping the middle "++" to become "+--+".
Follow up: Derive your algorithm's runtime complexity.
Tips:
第一题的变形,和拿硬币类似,用DP+记忆化搜索做。
- 复杂度为O(n!!)的做法是一个一个把所有可以换成”--“的”++“都换好,然后看对手能不能赢,如果都不行,就return true。
The idea is try to replace every "++" in the current string s to "--" and see if the opponent can win or not, if the opponent cannot win, great, we win!
For the time complexity, here is what I thought, let's say the length of the input string s is n, there are at most n - 1 ways to replace "++" to "--" (imagine s is all "+++..."), once we replace one "++", there are at most (n - 2) - 1 ways to do the replacement, it's a little bit like solving the N-Queens problem, the time complexity is (n - 1) x (n - 3) x (n - 5) x ..., so it's O(n!!), double factorial.
- 复杂度为O(n^2)的优化是加一个HashMap,把之前所有的结果都记录下来,可以直接调用。
Code:
naive:
public boolean canWin(String s) {
if (s == null || s.length() < 2) {
return false;
}
for (int i = 0; i < s.length() - 1; i++) {
if (s.startsWith("++", i)) {
String t = s.substring(0, i) + "--" + s.substring(i + 2);
if (!canWin(t)) {
return true;
}
}
}
return false;
}
optimization:
public boolean canWin(String s) {
if (s == null || s.length() < 2) {
return false;
}
HashMap<String, Boolean> winMap = new HashMap<String, Boolean>();
return helper(s, winMap);
}
public boolean helper(String s, HashMap<String, Boolean> winMap) {
if (winMap.containsKey(s)) {
return winMap.get(s);
}
for (int i = 0; i < s.length() - 1; i++) {
if (s.startsWith("++", i)) {
String t = s.substring(0, i) + "--" + s.substring(i+2);
if (!helper(t, winMap)) {
winMap.put(s, true);
return true;
}
}
}
winMap.put(s, false);
return false;
}