打表法练习之吃草问题

题目描述

假设现在有两只动物吃草,每次只能吃4的次幂的草,也就是1、4、16等等,现在,给你一个整数N,代表总共有多少草,两只动物,只能交替吃草,有先手和后手区别,假设动物都绝顶聪明,哪只动物先吃完草,哪只就赢,请你求出N份草时,是先手赢还是后手赢?

思路分析

因为动物绝顶聪明,因此,可以递归尝试先手吃1份时,先手能不能赢,只要能赢,因为绝顶聪明,那么先手的肯定会按照这个策略吃草,因此,结果就是先手赢。先手吃草从1、4、16依次尝试,直到接近N时,如果先手的所有可能都递归尝试完,还不能找出一种先手赢的方法,那就后手赢。
递归base case:
当草的数量降低到4以下时,可以直接出结果:
4:先手赢
3:先手拿1后手拿1先手拿1,先手赢
2:先手拿1后手拿1,后手赢
1:先手赢
0:无意义
递归函数:
递归需要想明白一个问题,那就是,当先后拿完,到后手的时候,因为两个动物都绝顶聪明嘛,因此,此时,后手拿的时候,其实,如果不考虑他之前的情况,到他的时候,其实,他就是先手拿,因此,我们只需要一种先手函数就行了,无论先手还是后手,都绝顶聪明,都会选择自己能赢的策略,因此是同一个递归函数。还有,如果后手返回的是后手赢,其实,就是先手赢了。因为,后手拿的时候,结果是后手赢,对于后手来说,此时他是先手,拿他的后手赢了,其实不就是另一个动物赢了嘛,另一个就是先手,一共就他俩玩。

代码

    public static String win1(int n){
        if(n<=0){
            return "出的毛线题,丢雷老母嘿哟";
        }
        if(n<=4){
            return n==2? "后手赢" : "先手赢";
        }
        int num=1;
        while (num<=n){
            //后手的后手赢了,还是先手赢
            if(win1(n-num).equals("后手赢")){
                return "先手赢";
            }
            num=num*4;
        }
        //所有情况都不能先手赢,再聪明绝顶也不行了,只能后手赢了
        return "后手赢";
    }

运行结果前20:
1:先手赢
2:后手赢
3:先手赢
4:先手赢
5:后手赢
6:先手赢
7:后手赢
8:先手赢
9:先手赢
10:后手赢
11:先手赢
12:后手赢
13:先手赢
14:先手赢
15:后手赢
16:先手赢
17:后手赢
18:先手赢
19:先手赢
20:后手赢

啥规律看明白没?怎么用打表法改呢?

打表法改进

所谓打表法,就是当你发现结果有规律时,就可以不考虑原本问题是啥,直接将规律用代码实现出来,这样的话,时间复杂度相较于原本的递归代码,直接能提升到O(1)的水平。

代码

    public static String win2(int n){
        if(n%5==2||n%5==0){
            return "后手赢";
        }else {
            return "先手赢";
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值