Skip to content

299. 猜数字游戏

解题过程

INFO

题目链接 你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下: 写出一个秘密数字,并请朋友猜这个数字是多少。朋友每猜测一次,你就会给他一个包含下述信息的提示: 猜测数字中有多少位属于数字和确切位置都猜对了(称为 "Bulls",公牛), 有多少位属于数字猜对了但是位置不对(称为 "Cows",奶牛)。也就是说,这次猜测中有多少位非公牛数字可以通过重新排列转换成公牛数字。 给你一个秘密数字 secret 和朋友猜测的数字 guess ,请你返回对朋友这次猜测的提示。 提示的格式为 "xAyB" ,x 是公牛个数, y 是奶牛个数,A 表示公牛,B 表示奶牛。 请注意秘密数字和朋友猜测的数字都可能含有重复数字

javascript
/**
 * @link https://leetcode.cn/problems/bulls-and-cows/
 * @title 299. 猜数字游戏
 * @description 你在和朋友一起玩 猜数字(Bulls and Cows)游戏,该游戏规则如下:
 * 写出一个秘密数字,并请朋友猜这个数字是多少。朋友每猜测一次,你就会给他一个包含下述信息的提示:
 * 猜测数字中有多少位属于数字和确切位置都猜对了(称为 "Bulls",公牛),
 * 有多少位属于数字猜对了但是位置不对(称为 "Cows",奶牛)。也就是说,这次猜测中有多少位非公牛数字可以通过重新排列转换成公牛数字。
 * 给你一个秘密数字 secret 和朋友猜测的数字 guess ,请你返回对朋友这次猜测的提示。
 * 提示的格式为 "xAyB" ,x 是公牛个数, y 是奶牛个数,A 表示公牛,B 表示奶牛。
 * 请注意秘密数字和朋友猜测的数字都可能含有重复数字
 * @param {string} secret
 * @param {string} guess
 * @return {string}
 */
// 解法一
// 思路:没有做出来
var getHint = function(secret, guess) {
  let bulls = 0
  let cows = 0
  const cowsM = new Map()
  const secretMap = new Map()

  for (const key of secret) {
    secretMap.set(key, (secretMap.get(key) || 0) + 1)
  }

  for (let i = 0; i < guess.length; i++) {
    if (secret[i] === guess[i]) {
      // 猜中
      bulls++
      secretMap.set(guess[i], secretMap.get(guess[i]) - 1)

      if (secretMap.get(guess[i]) < 0) {
        cows--
      }
    } else {
      // 没猜中,判断是否是奶牛
      if (secret.includes(guess[i]) && (!cowsM.has(guess[i]) || cowsM.get(guess[i]) <= secretMap.get(guess[i]))) {
        // 奶牛的数量不能多余secret的数字,多余的重复数字没必要计算
        secretMap.set(guess[i], (secretMap.get(guess[i]) || 0) - 1)
        if (secretMap.get(guess[i]) >= 0) {
          cows++
        }

        cowsM.set(guess[i], (cowsM.get(guess[i]) || 0) + 1)
      }
    }
  }

  return `${bulls}A${cows}B`
};

// 解法二
// 思路:官方题解思路:相同位置值直接统计公牛数量,否则统计两个字符串数组对应数字数量,然后遍历取最小值累加即可
var getHint = function(secret, guess) {
  let bulls = 0
  let cows = 0
  const bullsArr = new Array(10).fill(0)
  const cowsArr = new Array(10).fill(0)

  for (let i = 0; i < guess.length; i++) {
    if (secret[i] === guess[i]) {
      bulls++
    } else {
      bullsArr[secret[i]]++
      cowsArr[guess[i]]++
    }
  }

  for (let i = 0; i < bullsArr.length; i++) {
    cows += Math.min(bullsArr[i], cowsArr[i])
  }

  return `${bulls}A${cows}B`
}

// const result = getHint('1807', '7810') // 1A3B
const result = getHint('1123', '0111') // 1A1B
// const result = getHint('1122', '2211') // 0A4B
// const result = getHint('1122', '1222') // 3A0B
// const result = getHint('1122', '0001') // 0A1B
// const result = getHint('1423', '1122') // 2A0B
console.log(result)

解题感受

时间问题,没做出来,看了官方题解大概意思,写了一遍,主要思路公牛数量很好统计,主要奶牛的数量计算很巧妙利用两个字符数组的对应值判断取小的数累加。快速的解决奶牛计算考虑的很多问题

优质题解