LeeCode - 除数博弈

180 阅读2分钟

LeeCode - 除数博弈

题目:

爱丽丝和鲍勃一起玩游戏,他们轮流行动。爱丽丝先手开局。

最初,黑板上有一个数字 N 。在每个玩家的回合,玩家需要执行以下操作:

选出任一 x,满足 0 < x < N 且 N % x == 0 。 用 N - x 替换黑板上的数字 N 。 如果玩家无法执行这些操作,就会输掉游戏。

只有在爱丽丝在游戏中取得胜利时才返回 true,否则返回 false。假设两个玩家都以最佳状态参与游戏。

示例 1:

输入:2 输出:true 解释:爱丽丝选择 1,鲍勃无法进行操作。 示例 2:

输入:3 输出:false 解释:爱丽丝选择 1,鲍勃也选择 1,然后爱丽丝无法进行操作。

分析:

第一反应我是去模拟这个游戏过程,也就是递推计算,这里我使用了一个数组去保存符合0 < x < N || N % x == 0要求的数字,然后通过 x 随机去取得其中的一个数,这里考虑到进行的终点是N == 2 || 3,因为当初始N为偶数时,X只能取偶数,最终将会取到2,而奇数则取到有可能取到2或者3,因为可以一直取1,这样N值将会在奇偶数之间摇摆,直到3

我这里一开始没看清楚题目假设两个玩家都以最佳状态参与游戏,既然是最佳状态,那代表着能赢肯定赢,在 初始N为偶数的时候,爱丽丝只要一直拿1,鲍勃就不得不拿奇数,而偶数 - 奇数 - 1 = 偶数,故当N = 2的时候,爱丽丝赢。反之当N为奇数的时候,爱丽丝只能先手拿奇数,鲍勃只要一直取1,鲍勃赢。

我的答案:

答案:

var divisorGame = function (N, name) { //这个 name 用来描述此时取值的人 name == 1 ? 爱丽丝 :鲍勃
  if (N == 1) { // N == 1 就没法玩了
    return false
  }
  let arr = [] // 保存符合要求的数字
  for (let i = 0; i < N; i++) {
    if (N % i == 0 && i != 0) {
      arr.push(i)
      console.log(arr)
    }
  }
  // 这里当两个人瞎玩,从满足条件的数字内取得随机数
  let x = arr[parseInt(Math.random() * arr.length)]  
  if (N == 2) { // 判断递归终点
    if (name == 1) {
      return console.log("true")
    }else {
      return console.log("false") // 打印是为了在控制台看的见
    }
  } else if (N == 3) {
    if (name == 2) {
      return console.log("true")
    } else {
      return console.log("false")
    }
  }
  name == 1 ? 2 : 1
  divisorGame(N - x, name) // 递归
};
divisorGame(30, 1) // 测试一下,1 代表爱丽丝起手

结果:提交失败

标准解法

具体的思路上面已经说清楚了,在条件为假设两个玩家都以最佳状态参与游戏的情况下:

/**
 * @param {number} N
 * @return {boolean}
 */
var divisorGame = function(N) {
    return (N % 2 == 0)
};

结果:提交成功

耗时:80ms

内存:33.7MB

审题不仔细,做题两行泪。。。