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;
        }
    }
    人生没有彩排,每一天都是现场直播
  • 相关阅读:
    个人冲刺二(7)
    个人冲刺二(6)
    个人冲刺二(5)
    个人冲刺二(4)
    对称二叉树 · symmetric binary tree
    108 Convert Sorted Array to Binary Search Tree数组变成高度平衡的二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    pp 集成工程师 mism师兄问一问
    17. Merge Two Binary Trees 融合二叉树
    270. Closest Binary Search Tree Value 二叉搜索树中,距离目标值最近的节点
  • 原文地址:https://www.cnblogs.com/timfruit/p/11616262.html
Copyright © 2011-2022 走看看