zoukankan      html  css  js  c++  java
  • 算法

    算法 - leetcode 292 Nim Game

     一丶题目

    你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。你作为先手。
    
    你们是聪明人,每一步都是最优解。 编写一个函数,来判断你是否可以在给定石头数量的情况下赢得游戏。
    
    
    输入: 4
    输出: false 
    解释: 如果堆中有 4 块石头,那么你永远不会赢得比赛;
         因为无论你拿走 1 块、2 块 还是 3 块石头,最后一块石头总是会被你的朋友拿走。

    二丶思路

      1) 先尝试使用暴力解决--递归

      

    class Solution {
        public boolean canWinNim(int n) {
            if(n<=0){
                return false;
            }
            if(n<=3){
                return true;
            }
            if(!friendCanWinNim(n-1)){ //拿1块
                return true;
            }
            if(!friendCanWinNim(n-2)){ //拿2块
                return true;
            }
            if(!friendCanWinNim(n-3)){ //拿3块
                return true;
            }
            return false;
        }
    
        //朋友拿, 朋友是否可以赢
        private boolean friendCanWinNim(int n){
            if(n<=0){
                return false;
            }
            if(n<=3){
                return true;
            }
            if(!canWinNim(n-1)){ //拿1块
                return true;
            }
            if(!canWinNim(n-2)){ //拿2块
                return true;
            }
            if(!canWinNim(n-3)){ //拿3块
                return true;
            }
            return false;
        }
    }

      2) 出现超时的现象,缓存中间结果

    class Solution {
        Map<Integer, Boolean> resultMap =new HashMap<Integer, Boolean>(); //结果
        
        public boolean canWinNim(int n) {
            if(n<=0){
                return false;
            }
            if(n<=3){
                return true;
            }
            if(results[n]!=null){
                return results[n];
            }
    
            boolean result=false;
            if(!friendCanWinNim(n-1)){ //拿1块
                result=true;
                resultMap.put(n, result);return result;
            }
            if(!friendCanWinNim(n-2)){ //拿2块
                result=true;
                resultMap.put(n, result);return result;
            }
            if(!friendCanWinNim(n-3)){ //拿3块
                result=true;
                resultMap.put(n, result);return result;
            }
    
            result=false;
            resultMap.put(n, result);return result;
        }
    
        //朋友拿, 朋友是否可以赢
        private boolean friendCanWinNim(int n){
            if(n<=0){
                return false;
            }
            if(n<=3){
                return true;
            }
            if(!canWinNim(n-1)){ //拿1块
                return true;
            }
            if(!canWinNim(n-2)){ //拿2块
                return true;
            }
            if(!canWinNim(n-3)){ //拿3块
                return true;
            }
            return false;
        }
    }

      3) 递归过大, 出现栈溢出异常, 将递归改成for循环 (类似动态规划)

    class Solution {
        Map<Integer, Boolean> resultMap =new HashMap<Integer, Boolean>(); //缓存先手的结果
        public boolean canWinNim(int n) {
           if(n<=0){
                return false;
            }
            // 初始化
            resultMap.put(1, true);
            resultMap.put(2, true);
            resultMap.put(3, true);
    
            boolean result1, result2, result3;
            for(int i=4;i<=n;i++){
                // 拿1块
                result1=resultMap.get(i-1);
    
                // 拿2块
                result2=resultMap.get(i-2);
    
                // 拿3块
                result3=resultMap.get(i-3);
    
                if(!result1 || !result2 || !result3){
                    resultMap.put(i, true);
                }else {
                    resultMap.put(i, false);
                }

           System.out.println(i+" -> "+resultMap.get(i)); }
    return resultMap.get(n); } }

      4) 仍然出现超时, (打印中间结果可发现规律 T_T 这里看了别人的解释)

    class Solution {
        public boolean canWinNim(int n) {
            //规律题
            // 3+1  必输
            return n%(3+1)!=0;
        }
    }
    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    96. Unique Binary Search Trees1和2
    576. Out of Boundary Paths
    686. Repeated String Match判断字符串重复几次可以包含另外一个
    650. 2 Keys Keyboard
    Penetration Test
    Penetration Test
    Penetration Test
    Penetration Test
    CISSP 考试经验分享
    2019-2020 ICPC Asia Hong Kong Regional Contest J—Junior Mathematician 数位dp
  • 原文地址:https://www.cnblogs.com/timfruit/p/11616262.html
Copyright © 2011-2022 走看看