294. Flip Game II

最后更新

三刷。

某一个状态下不能赢,说明上一个状态赢了,上上个状态输了,上上上个状态赢了。。但是越往上状态越是不一定的。。

所谓的状态其实就是input的情况。 这个题更像是DFS+状态记录,只不过提前结束的情况比较早。

public class Solution {
    
    Map<String, Boolean> map = new HashMap<>();
    
    public boolean canWin(String s) {
        if (s.length() < 2) return false;
        
        boolean win = false;
        
        char[] strs = s.toCharArray();
        for (int i = 1; i < strs.length; i++) {
            if (!(strs[i] == '+' && strs[i-1] == '+')) continue;
            strs[i] = '-';
            strs[i-1] = '-';
            String tempS = new String(strs);
            win = !canWin(tempS);
            if (win) {
                map.put(tempS, win);
                return true;
            }
            strs[i] = '+';
            strs[i-1] = '+';
        }
        
        return win;
    }
}

一刷。

这个题上来没找对思路,以为有什么数学思想在里面,列举了2-9的情况,也没研究个明白。

然后看TAG是BACK-TRACK。。似乎只能是这个样。

无非是看当前走这一步,然后下一步该你了,你下一步能不能赢,不能赢就是我赢了。。

time complexity应该是指数级别的。。

用DP ARRAY记录可以省去重复计算。。

public class Solution 
{
    Map<String,Boolean> map = new HashMap<String,Boolean>();
    
    public boolean canWin(String s) 
    {
        if(s.length() < 2) return false;
        if(map.containsKey(s)) return map.get(s);
        
        
        char[] str = s.toCharArray();
        
        for(int i = 0; i < str.length-1;i++)
        {
            
            if(str[i] == '+' && str[i+1] == '+')
            {
                str[i] = '-';
                str[i+1] = '-';
                String tempStr = new String(str);
                if(!canWin(tempStr))
                {
                     map.put(tempStr,false);
                     return true;
                }
                str[i] = '+';
                str[i+1] = '+';
            }
        }
        
        map.put(s,false);
        return false;
        
    }
    

}


二刷

赢的标致是,走完这步对方无路可走。。。

如果对方下一步无路可走,就证明赢了;如果有路,这步就不这么走,试试别的走法。

top-down里使用记忆的一种典型。唯一的不同是这个题可以提前结束。

public class Solution {
    
    Map<String, Boolean> map = new HashMap<>();
    public boolean canWin(String s) {
        
        if (s.length() < 2) return false;
        if (map.containsKey(s)) return map.get(s);
        
        char[] chArray = s.toCharArray();
        boolean res = false;
        for (int i = 0; i < chArray.length - 1; i++) {
            if (chArray[i] == '+' && chArray[i+1] == '+') {
                chArray[i] = '-';
                chArray[i+1] = '-';
                String nextS = new String(chArray);
                boolean nextPlayer = canWin(nextS);
                if (!nextPlayer) {
                    res = true;
                    break;
                } 
                chArray[i] = '+';
                chArray[i+1] = '+';
            } 
        }
        map.put(s, res);
        return res;
    }
}

这里的复杂度比较麻烦。。

上面是用了记忆搜索的办法。

比如有N个 +

算了半天算乱了。。直接给别人的答案吧。。

(https://discuss.leetcode.com/topic/27282/theory-matters-from-backtracking-128ms-to-dp-0ms)

T(N) = (N-2) * T(N-2) = (N-2) * (N-4) * T(N-4) ... = (N-2) * (N-4) * (N-6) * ... ~ O(N!!)

还有O(n^2)的做法,看了两行就不想看了。

原文地址:https://www.cnblogs.com/reboot329/p/5955093.html