每日一题算法:2020年9月1日 [预测赢家] PredictTheWinner

2020年9月1日 预测赢家 PredictTheWinner

在这里插入图片描述

class Solution {
    public boolean PredictTheWinner(int[] nums) {

    }
}

解题思路:

一般来说,这种游戏规则类题目考验的是你的逻辑能力,看你能否察觉到游戏的本质是什么,其实有很多的这种小游戏能够看穿本质之后就会变得很无聊。

思路1,使用递归。

我们的问题是,玩家1能否获胜。

那么我们可以试着改变思路,把问题变成,当玩家1选择的第1个或者玩家1选择了最后一个之后,玩家2是否能够得到的最大分数是否会比当时玩家1拿到的最大分数多出玩家1已经拿到的分数。

下面这个算法没有用到任何一点技巧,知识单纯的递归了所有可能性,我觉得时间大概率是超限了的。
在这里插入图片描述

    int[] nums;
    public boolean PredictTheWinner(int[] nums) {
        this.nums=nums;
        if (canWin(0,nums.length-1 )>=0){
            return true;
        }else 
            return false;
    }
    //返回先拿的比后拿的最多多多少分
    public int  canWin(int start,int end){
        
        if (end<start){
            return 0;
        }
        
        return Integer.max(nums[start]-canWin(start+1,end),nums[end]-canWin(start,end-1));
    }

但是不可能这样就满意了的,肯定是要优化的,那么怎么优化呢?

优化1:

优化的最基础的一个方式,用空间换时间,我这里用一个len*len大小的二维数组记录递归过程中计算的结果,因为计算过程有一些是重复的,比如

1,2,3,4,5

第一次递归,玩家1拿1,玩家2拿5。剩下的3个继续递归。

第二次递归,玩家1拿5,玩家2拿1,剩下三个相同的但是任然需要递归。

我们的目的就是,剩下的三个我们记录下来,这样第二次递归之前发现已经计算过就不用递归了。这也算是一种递归的剪枝算法吧。

完美
在这里插入图片描述

    int[] nums;
    Integer[][] map;
    public boolean PredictTheWinner(int[] nums) {
        this.nums=nums;
        map=new Integer[nums.length][nums.length];
        if (canWin(0,nums.length-1 )>=0){
            return true;
        }else
            return false;
    }
    //返回先拿的比后拿的最多多多少分
    public int  canWin(int start,int end){

        if (end<start){
            return 0;
        }
        if (map[start][end]==null){
            int num1=nums[start]-canWin(start+1,end);
            int num2=nums[end]-canWin(start,end-1);
            
            map[start][end]=Integer.max(num1,num2);
            return map[start][end];
        }
        else return map[start][end];
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值