LeetCode 1128.等价多米诺骨牌对的数量:计数

【LetMeFly】1128.等价多米诺骨牌对的数量:计数

力扣题目链接:https://leetcode.cn/problems/number-of-equivalent-domino-pairs/

给你一组多米诺骨牌 dominoes

形式上,dominoes[i] = [a, b]dominoes[j] = [c, d] 等价 当且仅当 (a == cb == d) 或者 (a == db == c) 。即一张骨牌可以通过旋转 0 度或 180 度得到另一张多米诺骨牌。

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

 

示例 1:

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

示例 2:

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

 

提示:

  • 1 <= dominoes.length <= 4 * 104
  • dominoes[i].length == 2
  • 1 <= dominoes[i][j] <= 9

解题方法:计数

使用一个哈希表(或数组)统计每多米诺骨牌的出现次数。

既然[1, 2][2, 1]等价,那么不妨将他们视为同一骨牌来看待。

即:当[a, b]a > b时,将[a, b]调整为[b, a]

哈希表如何设计(如何将两个数映射为一个数)?

(a - 1) * 9 + (b - 1)即可。

这样,哈希表的大小9 * 9 = 81即可。

如何计算“对数”?

两种方法:

  1. 统计出每种骨牌出现次数后,遍历哈希表,若这种骨牌出现了 t t t次,则可形成 t ( t − 1 ) 2 \frac{t (t - 1)}{2} 2t(t1)对骨牌

  2. 假设在骨牌 v v v加入哈希表之前哈希表中 v v v出现了 t t t次,那么就先将答案加上 t t t再将哈希表中 v v v出现次数加一。

  • 时间复杂度:方法一 O ( l e n ( d o m i n o e s ) ) O(len(dominoes)) O(len(dominoes));方法二 O ( l e n ( d o m i n o e s ) + C 2 ) O(len(dominoes)+C^2) O(len(dominoes)+C2)。其中 C = 9 C=9 C=9
  • 空间复杂度 O ( C 2 ) O(C^2) O(C2)

AC代码

C++ - 方法二
/*
 * @Author: LetMeFly
 * @Date: 2025-05-04 14:26:01
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-05-04 15:02:06
 */
#if defined(_WIN32) || defined(__APPLE__)
#include "_[1,2]toVector.h"
#endif

class Solution {
private:
    inline int pair2int(vector<int>& v) {
        if (v[0] > v[1]) {
            return (v[1] - 1) * 9 + (v[0] - 1);
        }
        return (v[0] - 1) * 9 + (v[1] - 1);
    }
public:
    int numEquivDominoPairs(vector<vector<int>>& dominoes) {
        int times[81] = {0};
        for (vector<int>& v : dominoes) {
            times[pair2int(v)]++;
        }
        int ans = 0;
        for (int i = 0; i < 81; i++) {
            ans += times[i] * (times[i] - 1) / 2;
        }
        return ans;
    }
};
C++ - 方法一
/*
 * @Author: LetMeFly
 * @Date: 2025-05-04 16:12:00
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-05-04 16:13:46
 */
#if defined(_WIN32) || defined(__APPLE__)
#include "_[1,2]toVector.h"
#endif

class Solution {
public:
    int numEquivDominoPairs(vector<vector<int>>& dominoes) {
        int times[81] = {0} ;
        int ans = 0;
        for (vector<int>& d : dominoes) {
            ans += times[d[0] < d[1] ? (d[0] - 1) * 9 + d[1] - 1 : (d[1] - 1) * 9 + d[0] - 1]++;
        }
        return ans;
    }
};
Python - 方法一
'''
Author: LetMeFly
Date: 2025-05-04 14:26:12
LastEditors: LetMeFly.xyz
LastEditTime: 2025-05-04 16:10:15
'''
from typing import List

class Solution:
    def numEquivDominoPairs(self, dominoes: List[List[int]]) -> int:
        times = [0] * 81
        ans = 0
        for a, b in dominoes:
            v = (a - 1) * 9 + (b - 1) if a < b else (b - 1) * 9 + (a - 1)
            ans += times[v]
            times[v] += 1
        return ans
Java - 方法一
/*
 * @Author: LetMeFly
 * @Date: 2025-05-04 14:26:15
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-05-04 16:15:28
 */
class Solution {
    public int numEquivDominoPairs(int[][] dominoes) {
        int[] times = new int[81];
        int ans = 0;
        for (int[] d : dominoes) {
            ans += times[d[0] < d[1] ? (d[0] - 1) * 9 + d[1] - 1 : (d[1] - 1) * 9 + d[0] - 1]++;
        }
        return ans;
    }
}
Go - 方法一
/*
 * @Author: LetMeFly
 * @Date: 2025-05-04 14:26:18
 * @LastEditors: LetMeFly.xyz
 * @LastEditTime: 2025-05-04 16:18:34
 */
package main

func numEquivDominoPairs(dominoes [][]int) (ans int) {
    times := make([]int, 81)
    for _, d := range dominoes {
        var v int
        if d[0] < d[1] {
            v = (d[0] - 1) * 9 + d[1] - 1
        } else {
            v = (d[1] - 1) * 9 + d[0] - 1
        }
        ans += times[v]
        times[v]++
    }
    return
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tisfy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值