【力扣刷题】预测赢家

🔗 题目链接

题目描述

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

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

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

题目分析

题目有一句”你可以假设每个玩家的玩法都会使他的分数最大化“很关键,说明两个人都是绝对聪明的人,他们的想法都是一样的。

这道题我们发现数组 nums 是不断变化的,所以可以用动态规划的思路来做。

dp[i][j]表示的在[i, j]所组成的子数组,先手玩家比后手玩家多得的分数(正数则为多得,负数则为少得),动态规划方程可以表示为:

在这里插入图片描述

[i, j] 数组中,玩家 1 作为先手,有两种选择:

  • 选择nums[i],那么剩下的[i+1, j]则由玩家 2 作为先手来选择
    • [i+1, j]中,玩家 2 作为先手会比玩家 1 多得的分数是dp[i+1][j]
  • 选择nums[j],那么剩下的[i, j-1]则由玩家 2 作为先手来选择
    • [i, j-1]中,玩家 2 作为先手会比玩家 1 多得的分数是dp[i][j-1]

在这里插入图片描述

我们假设nums数组为[1, 5, 8, 3, 5, 2],则表示为:

nums012345
158352

那么,我们可以得到一个 6×6 的二维表格,只需要把表格上半部分填充完整即可。

dp[i][j]012345
01
1-5
2--8
3---3
4----5
5-----2

首先,我们填充j=1列,很容易发现,dp[0][1]的结果是 4。

dp[i][j]012345
014
15
28
33
45
52

接下来,我们填充j=2列:

dp[i][j]012345
01441
1530
285
33
45
52

接下来,我们填充j=3列:

dp[i][j]012345
01441
1530
285
33
45
52

接下来,我们填充j=4列:

dp[i][j]012345
014414
15305
2856
332
45
52

最后,,我们填充j=5列:

dp[i][j]012345
0144144
15305-3
28568
3320
453
52

最后,我们发现,玩家 1 是胜利的。

题解代码

/**
 * @param {number[]} nums
 * @return {boolean}
 */
var PredictTheWinner = function (nums) {
  const len = nums.length;
  const dp = new Array(len);
  for (let i = 0; i < len; i++) {
    dp[i] = new Array(len);
    dp[i][i] = nums[i];
  }
  for (let j = 1; j < len; j++) {
    for (let i = j - 1; i >= 0; i--) {
      dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]);
    }
  }
  return dp[0][len - 1] >= 0;
};

运行结果

在这里插入图片描述

代码基地

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值