文章

[LeetCode] 每日一题 1128. 等价多米诺骨牌对的数量(排序 + 哈希)

题目描述

给你一组多米诺骨牌 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) 的数量。

题目链接

https://leetcode.cn/problems/number-of-equivalent-domino-pairs

示例输入

示例 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

解题思路

这道题本质是一个组合统计问题,我们需要找出所有满足“等价”条件的多米诺骨牌对 (i, j)。题目中定义的等价关系其实比较宽松:即 [a, b][b, a] 被视为相同。因此,我们可以通过一个简单排序策略来统一它们的表示方式。

具体来说,我们将每张牌 [a, b] 变换为 min(a, b) * 10 + max(a, b),这样就能将 [2, 5][5, 2] 统一表示为 25,从而方便哈希处理。

由于数字范围限定在 1~9,我们可以直接用一个大小为 100 的数组模拟哈希表,统计每个牌型出现的次数。遍历每个多米诺时,假设当前是 j 位置的牌,之前已经统计过所有 i 位置的牌(i < j),我们只需要查一下之前这个牌型出现了几次即可,这些就构成了等价对。

这种做法既高效又简洁,非常适合面试中快速实现。

代码实现

class Solution {
    public int numEquivDominoPairs(int[][] dominoes) {
        int[] cnt = new int[100];
        int ans = 0;
        for (int[] domino : dominoes) {
            int top = domino[0], bottom = domino[1];
            if (top > bottom) {
                top ^= bottom;
                bottom ^= top;
                top ^= bottom;
            }
            int pos = 10 * top + bottom;
            ans += cnt[pos]++;
        }
        return ans;
    }
}

复杂度分析

  • 时间复杂度:O(n)
    只遍历一次所有骨牌,每张骨牌的处理是常数时间

  • 空间复杂度:O(1)
    使用固定长度的计数数组(100个元素),即常数级空间

总结

这道题是那种一眼看过去可能不清楚统计逻辑,但理清本质就非常容易下手的题。我的解法是直接把等价的两个方向规整成一种形式,再用计数数组模拟哈希统计。特别适合拿来练习哈希映射技巧 + 前缀累加组合数的思想,属于思维清晰即可高效拿分的题型💡

希望这篇分享能为你带来启发!如果你有任何问题或建议,欢迎在评论区留言,与我共同交流探讨。

License:  CC BY 4.0