486. 预测赢家

给你一个整数数组 nums 。玩家 1 和玩家 2 基于这个数组设计了一个游戏。

玩家 1 和玩家 2 轮流进行自己的回合,玩家 1 先手。开始时,两个玩家的初始分值都是 0 。每一回合,玩家从数组的任意一端取一个数字(即,nums[0] 或 nums[nums.length - 1]),取到的数字将会从数组中移除(数组长度减 1 )。玩家选中的数字将会加到他的得分上。当数组中没有剩余数字可取时,游戏结束。

如果玩家 1 能成为赢家,返回 true 。如果两个玩家得分相等,同样认为玩家 1 是游戏的赢家,也返回 true 。你可以假设每个玩家的玩法都会使他的分数最大化。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/predict-the-winner
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

记忆化搜索

import java.util.Arrays;

class Solution {

    private int n;

    private int[] nums;

    private int[][] first;

    private int[][] second;

    private int first(int left, int right) {
        if (first[left][right] == -1) {
            if (left == right) {
                first[left][right] = nums[left];
            } else {
                first[left][right] = Math.max(nums[left] + second(left + 1, right), nums[right] + second(left, right - 1));
            }
        }
        return first[left][right];
    }

    private int second(int left, int right) {
        if (second[left][right] == -1) {
            if (left == right) {
                second[left][right] = 0;
            } else {
                second[left][right] = Math.min(first(left + 1, right), first(left, right - 1));
            }
        }
        return second[left][right];
    }

    public boolean PredictTheWinner(int[] nums) {
        this.n = nums.length;
        this.nums = nums;
        this.first = new int[n][n];
        this.second = new int[n][n];
        for (int i = 0; i < n; ++i) {
            Arrays.fill(first[i], -1);
            Arrays.fill(second[i], -1);
        }
        return first(0, n - 1) >= second(0, n - 1);
    }
}

动态规划

import java.util.Arrays;

class Solution {

    private int n;

    private int[] nums;

    private int[][] first;

    private int[][] second;
    
    private boolean dp() {
        for (int i = 0; i < n; ++i) {
            first[i][i] = nums[i];
        }
        for (int left = n - 1; left >= 0; --left) {
            for (int right = left + 1; right < n; ++right) {
                first[left][right] = Math.max(nums[left] + second[left + 1][right], nums[right] + second[left][right - 1]);
                second[left][right] = Math.min(first[left + 1][right], first[left][right - 1]);
            }
        }
        return first[0][n - 1] >= second[0][n - 1];
    }

    public boolean PredictTheWinner(int[] nums) {
        this.n = nums.length;
        this.nums = nums;
        this.first = new int[n][n];
        this.second = new int[n][n];
        return dp();
    }
}
posted @ 2021-12-28 10:50  Tianyiya  阅读(55)  评论(0)    收藏  举报