给定一个表示分数的非负整数数组。 玩家 1 从数组任意一端拿取一个分数,随后玩家 2 继续从剩余数
组任意一端拿取分数,然后玩家 1 拿,…… 。每次一个玩家只能拿取一个分数,分数被拿取之后不再可
取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最
大化。
两个值的时候必然是取较大的,三个值,取一个能使自己分数和最大的,后手必然留较小的给先手,因
此先手选一个值加上该较小值最大化
static int maxScore(int[] nums, int l, int r) {//剩下一个值,只能取该值if (l == r) {return nums[l];}int selectLeft = 0;int selectRight = nums.length - 1;//剩下大于两个值,先手选一边(使自己得分最高的一边),后手则选使对手得分最低的一边if ((r - l) >= 2) {selectLeft = nums[l] +Math.min(maxScore(nums, l + 2, r), maxScore(nums, l + 1, r - 1));selectRight = nums[r] +Math.min(maxScore(nums, l + 1, r - 1), maxScore(nums, l, r - 2));}//剩下两个值,取较大的if ((r - l) == 1) {selectLeft = nums[l];selectRight = nums[r];}return Math.max(selectLeft, selectRight);}int getScore(int[] nums, int start, int end) {int selectLeft;int selectRight;int gap = end - start;if (gap == 0) {return nums[start];} else if (gap == 1) {// 此时直接取左右的值就可以selectLeft = nums[start];selectRight = nums[end];} else if (gap >= 2) {// 如果gap大于2,递归计算selectLeft和selectRight// 计算的过程为什么用min,因为要按照对手也是最聪明的来计算。int num = getScore(nums, start + 1, end - 1);selectLeft = nums[start] +min(getScore(nums, start + 2, end), num);selectRight = nums[end] + min(num, getScore(nums, start, end - 2));}return max(selectLeft, selectRight);}bool PredictTheWinner(int[] nums) {int sum = 0;for (int i : nums) {sum += i;}int player1 = getScore(nums, 0, nums.size() - 1);int player2 = sum - player1;// 如果最终两个玩家的分数相等,那么玩家 1 仍为赢家,所以是大于等于。return player1 >= player2;//return getScore(nums, 0, nums.size() - 1) >=0 ;}//差值int getScore(int[] nums, int start, int end) {if (end == start) {return nums[start];}int selectLeft = nums[start] - getScore(nums, start + 1, end);int selectRight = nums[end] - getScore(nums, start, end - 1);return max(selectLeft, selectRight);}
动态规划:使用二维数组存储差值
public boolean PredictTheWinner(int[] nums) {int length = nums.length;int[][] dp = new int[length][length];for (int i = 0; i < length; i++) {dp[i][i] = nums[i];}for (int i = length - 2; i >= 0; i--) {for (int j = i + 1; j < length; j++) {//j = i +1 因此可以优化为一维数组,下标位置相同才有值,据此推导其他的值//Math.max(nums[i] - dp[j][j], nums[j] - dp[j - 1][j - 1]);dp[i][j] = Math.max(nums[i] - dp[i + 1][j],nums[j] - dp[i][j - 1]);}}return dp[0][length - 1] >= 0;}
