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.html
Write a function to determine if the starting player can guarantee a win.git
Example:github
Input: Output: true Explanation: The starting player can guarantee a win by flipping the middle to become . s = "++++""++""+--+"
Follow up:
Derive your algorithm's runtime complexity.函数
这道题是以前那道 Flip Game 的拓展,让咱们判断先手的玩家是否能赢,能够穷举全部的状况,用回溯法来解题,思路跟上面那题相似,也是从第二个字母开始遍历整个字符串,若是当前字母和以前那个字母都是+,那么递归调用将这两个位置变为--的字符串,若是返回 false,说明当前玩家能够赢,结束循环返回 false。这里同时贴上热心网友 iffalse 的解释,这道题不是问 “1p是否会怎么选都会赢”,而是 “若是1p每次都选特别的两个+,最终他会不会赢”。因此 canWin 这个函数的意思是 “在当前这种状态下,至少有一种选法,可以让他赢”。而 (!canWin) 的意思就变成了 “在当前这种状态下,不管怎么选,都不能赢”。因此 1p 要看的是,是否存在这样一种状况,不管 2p 怎么选,都不会赢。因此只要有一个 (!canWin),1p 就能够肯定他会赢。这道题从博弈论的角度会更好理解。每一个 player 都想让本身赢,因此每轮他们不会随机选+。每一轮的 player 会选可以让对手输的+。若是不管如何都选不到让对手输的+,那么只能是当前的 player 输了,参见代码以下:post
解法一:url
class Solution { public: bool canWin(string s) { for (int i = 1; i < s.size(); ++i) { if (s[i] == '+' && s[i - 1] == '+' && !canWin(s.substr(0, i - 1) + "--" + s.substr(i + 1))) { return true; } } return false; } };
第二种解法和第一种解法同样,只是用 find 函数来查找 ++ 的位置,而后把位置赋值给i,而后仍是递归调用 canWin 函数,参见代码以下:spa
解法二:code
class Solution { public: bool canWin(string s) { for (int i = -1; (i = s.find("++", i + 1)) >= 0;) { if (!canWin(s.substr(0, i) + "--" + s.substr(i + 2))) { return true; } } return false; } };
Github 同步地址:htm
https://github.com/grandyang/leetcode/issues/294blog
相似题目:
Guess Number Higher or Lower II
参考资料:
https://leetcode.com/problems/flip-game-ii/
https://leetcode.com/problems/flip-game-ii/discuss/74033/4-line-Java-Solution
https://leetcode.com/problems/flip-game-ii/discuss/74010/Short-Java-and-Ruby
https://leetcode.com/problems/flip-game-ii/discuss/73962/Share-my-Java-backtracking-solution