leetcode刷题记录-2029. 石子游戏 IX - 找规律

210 阅读3分钟

「这是我参与2022首次更文挑战的第3天,活动详情查看:2022首次更文挑战

前言

今天的题目为博弈论类型的题目,第一次做这种题,刚开始的时候看到长长的题目很是懵逼,后来看了一些解析才发现这题比较简单,可以简化为简单的找规律过程。

题目描述

今天的题目为leetcode上的 2029. 石子游戏 IX 难度为 中等

  • Alice 和 Bob 再次设计了一款新的石子游戏。现有一行 n 个石子,每个石子都有一个关联的数字表示它的价值。给你一个整数数组 stones ,其中 stones[i] 是第 i 个石子的价值。

  • Alice 和 Bob 轮流进行自己的回合,Alice 先手。每一回合,玩家需要从 stones 中移除任一石子。

  • 如果玩家移除石子后,导致 所有已移除石子 的价值 总和 可以被 3 整除,那么该玩家就 输掉游戏 。

  • 如果不满足上一条,且移除后没有任何剩余的石子,那么 Bob 将会直接获胜(即便是在 Alice 的回合)。

  • 假设两位玩家均采用 最佳 决策。如果 Alice 获胜,返回 true ;如果 Bob 获胜,返回 false 。

示例 1:

输入:stones = [2,1]
输出:true
解释:游戏进行如下:
- 回合 1Alice 可以移除任意一个石子。
- 回合 2Bob 移除剩下的石子。
已移除的石子的值总和为 1 + 2 = 3 且可以被 3 整除。因此,Bob 输,Alice 获胜。

示例 2:

输入:stones = [2]
输出:false
解释:Alice 会移除唯一一个石子,已移除石子的值总和为 2 。 
由于所有石子都已移除,且值总和无法被 3 整除,Bob 获胜。

示例 3:

输入:stones = [5,1,2,4,3]
输出:false
解释:Bob 总会获胜。其中一种可能的游戏进行方式如下:
- 回合 1Alice 可以移除值为 1 的第 2 个石子。已移除石子值总和为 1 。
- 回合 2Bob 可以移除值为 3 的第 5 个石子。已移除石子值总和为 = 1 + 3 = 4 。
- 回合 3Alices 可以移除值为 4 的第 4 个石子。已移除石子值总和为 = 1 + 3 + 4 = 8 。
- 回合 4Bob 可以移除值为 2 的第 3 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 = 10.
- 回合 5Alice 可以移除值为 5 的第 1 个石子。已移除石子值总和为 = 1 + 3 + 4 + 2 + 5 = 15.
Alice 输掉游戏,因为已移除石子值总和(15)可以被 3 整除,Bob 获胜。

提示:

  • 1 <= stones.length <= 105
  • 1 <= stones[i] <= 104

题解

博弈论是二人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜的目的。简单的来说,就是两个人玩一个游戏,通过对方的选择去改变自己的选择为最优解,从而取得胜利。

寻找题目的规律

首先,题目会给我们一个 stone 的数组,这时我们可以看到,游戏的胜利失败条件为已移除石子的价值总和可以被 3 整除,这里我们就可以将这个数组做一个简化,因为当数组里的数据为0,或者为3,它们取出来以后对总价值会不会被3整除没有任何影响,以此类推,我们就可以把stone的价值分为三种类型,有 0 价值的,1 价值的,和 2 价值的 stone。我们分别将他们命名为 0,1,2。

再来我们可以发现,0 的取出完全不可能造成游戏失败,所以我们可以把它看成一次交换对手的过程,简单的说就是 0 为奇数的话,就相当于是由 Bob 先手了,而不是Alice。

最后,我们还剩下 1 和 2。这里就有点像找规律的一个过程,假设先不考虑 0 我们可以从先手的 Alice 记录下不会造成失败的取石头方式:

  1. 假设 Alice 先手取的是 1 的石子,那么 Bob 就只能取 1 ,以此可以推断出取石头的顺序为:1,1,2,1,2,1,2...
  2. 假设 Alice 先手取的是 2 的石子,那么 Bob 就只能取 2 ,以此可以推断出取石头的顺序为:2,2,1,2,1,2,1... 最后我们可以发现,Alice 想要获胜,必须是 Bob 没有可选的石子,在结合以上的对于 0 的分析,只要 stone 不全是 0 ,我们就可以分为两种情况,就是当 0 为奇数时或者 0 为偶数时:

stone0为奇数

image.png 画一张图来做一个推断,因为 0 为奇数,只是会交换先后手,和它具体的个数没有关系,那么我们就假设它是一个。然后像上图一样,Alice 以 2 开始,后面会进入循环,而打破这个循环让 Alice 胜利的方法只有一个,就是在 Bob 进入循环之后,不存在 1 这个选项了

image.png

类似上图这样,哪怕 2 再多,只要 1 数量不够,那么Bob就会失败,所以我们能得出 Alice 胜利的条件,就是 2 比 1 至少多3个的情况,当然,1 和 2 完全可以互换,所以 1 比 2 至少多3个的情况也能满足。

stone0为偶数

在 0 为偶数的时候,只要有至少一个 1 或者 2 ,相当于是不存在 0 的选项。那么可能出现的情况就只有上面列出来的 1,1,2,1,2,1,2... 或者 2,2,1,2,1,2,1... 以此我们也不难看出,Alice想要获胜,只有当 2 比 1 个数多或者相等的时候,也就是 2 >= 1,

image.png 当然我们还要去考虑数组结束或者全是 1 或者 2 的情况,这就都是 Bob 胜利了,所以综上所述,需要 1 大于等于一个,并且 2 大于等于一个。

代码

/**
 * @param {number[]} stones
 * @return {boolean}
 */
var stoneGameIX = function(stones) {
    let stone0 = 0, stone1 = 0, stone2 = 0;
    for (const stone of stones) {
        const type = stone % 3;
        if (type === 0) {
            ++stone0;
        } else if (type === 1) {
            ++stone1;
        } else {
            ++stone2;
        }
    }
  return stone0 % 2 === 0
    ? stone1 >= 1 && stone2 >= 1
    : stone1 - stone2 > 2 || stone2 - stone1 > 2
};

image.png