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;
        }
    }
    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    2017年5月24日 HTML 基础知识(二)
    2017年5月22日 HTML基础知识(一)
    尼采语录
    Unicode字符串和整数和浮点数
    转义字符
    python第一节
    C# ASP .NET WEB方向和WPF方向,我该如何去选择
    ORA-06550:line 1,column 7;PLS-00201:indentifer '存储过程' must be declared;...PL/SQL Statement ignored 问题
    C# WPF打印报表
    Sql Server 自定义数据类型
  • 原文地址:https://www.cnblogs.com/timfruit/p/11616262.html
Copyright © 2011-2022 走看看