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

题目描述:

给你一个由一些多米诺骨牌组成的列表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

blahblahblah,,,对于算法基础较为薄弱的我,一开始只能想到暴力解题。综合了诸多大佬的解题思路,不禁感慨,在此做了一个简单地汇总。

分析:

概括说来,题目的目的其实就是求出等价牌的排列组合。因此关键在于找出等价牌的数量,再运用排列组合公式即可求出答案。

比如对于[1,2]这张牌有n张等价牌,那么(i,j)的数量就是C(n,2),所以我们要做的是找出所有有等价牌的牌,然后找出它们对应等价牌的数量(count)。再count*(count-1)/2即可。(与顺序无关,因此要去重)

在此附上源代码(c++ version):

class Solution {
public:
    int numEquivDominoPairs(vector>& dominoes) 
    {
        int num = 0;
        map,int> total;
        for (int i=0;i

此外,题解给出的一种比较取巧的办法,我是想不出来,在此也做一下说明。(说明为摘录内容,自己还没理解透彻)

分析:

使用统一的编码对二元组进行编码,这里采用小的做十位数,大的做个位数的策略,然后使用一个vector进行计数,每次看当前编码已有的个数,使用当前的多米诺骨牌可以和之前的每一对形成新的一对,所以更新 num+=arr[rec];

class Solution {
public:
    int numEquivDominoPairs(vector>& dominoes) 
    {
        int num = 0;
        vector arr(100);
        for (auto it:dominoes)
        {
            int rec=it[0]>it[1]?it[1]*10+it[0]:it[0]*10+it[1];
            num+=arr[rec];
            arr[rec]++;
        }
        return num;
    }
};

我们再来看看用哈希表做,解题思路都大同小异,先上代码(java version):

public int numEquivDominoPairs3(int[][] dominoes) {
    Map map = new HashMap();
    for (int[] temp : dominoes) {
        int num = Math.min(temp[0], temp[1])*10
                + Math.max(temp[0], temp[1]);
        map.put(num, map.getOrDefault(num, 0)+1);
    }
    int result = 0;
    for (Integer times : map.values()) {
        result += times*(times-1)/2;
    }
    return result;
}
ps:再对“Map.getOrDefault(Object key, V defaultValue);”做一下简单的解释

如果在Map中存在key,则返回key所对应的的value。
如果在Map中不存在key,则返回默认值。
例如:
map.put(num, map.getOrDefault(num, 0) + 1);
表示:
value默认从1开始,每次操作后num对应的value值加1
可以用来统计数字出现的次数!

你可能感兴趣的:(1128. 等价多米诺骨牌对的数量)