每日一题 -- 简单-- 等价多米诺骨牌对的数量(1128)

96 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第2天,点击查看活动详情

题目:

给你一个由一些多米诺骨牌组成的列表 dominoes

如果其中某一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌,我们就认为这两张牌是等价的。

形式上,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价的前提是 a==c 且 b==d,或是 a==d 且 b==c

在 0 <= i < j < dominoes.length 的前提下,找出满足 dominoes[i] 和 dominoes[j] 等价的骨牌对 (i, j) 的数量。

示例:

输入:dominoes = [[1,2],[2,1],[3,4],[5,6]]
输出:1

提示:

  • 1 <= dominoes.length <= 40000
  • 1 <= dominoes[i][j] <= 9

🙇‍♂️ 感想:题目也是很清晰明了,找到相等的对,牌可以翻转。如果不考虑时间复杂度,上来就搞一个嵌套循环就搞定了。可惜题目有时间限制,可想而知超时了 🤣。那如何降低时间复杂度呢。

🙇‍♂️ 解题思路:可以使用哈希表将数值先循环遍历格式化一遍,将相同的值存到一起。使用一个map进行存值,key记得先转换为值类型存储,不然每次存进去的都不是相等的。如果map中存在该值,则该值+1即可,如果没有将值翻转过来判断是否存在,如果存在则,翻转值+1即可。如果都没有,则将值插入,并赋值为1即可。根据自己推到也不难推出,与斐波那契数列的差不多即:(n * (n - 1) )/ 2

function numEquivDominoPairs(dominoes: number[][]): number {
  let result: number = 0
  let map = new Map()
  for (let i = 0; i < dominoes.length; i++) {
    let str = dominoes[i].toString()
    if (map.has(str)) {
      let num = map.get(str)
      map.set(str, ++num)
    } else {
      let [m,n] = dominoes[i]
      if (map.has([n, m].toString())) {
        let num = map.get([n, m].toString())
        map.set([n, m].toString(), ++num)
      } else {
        map.set(str, 1)
      }
    }
  }
  for (let [key, value] of map.entries()) {
    if (value > 1) {
      result += (value * (value - 1)) /2
    }
  }
  return result
};