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