一. 问题描述
小F手里有一组多米诺骨牌,dominoes[i] = [a, b] 和 dominoes[j] = [c, d] 等价当且仅当 (a == c 且 b == d) 或者 (a == d 且 b == c)。也就是说,一张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张等价的多米诺骨牌。
现在,小F想知道在 0 <= i < j < dominoes.length 的前提下,有多少对多米诺骨牌是等价的。
测试样例
样例1:
输入:
dominoes = [[1, 2], [2, 1], [3, 4], [5, 6]]
输出:1
样例2:
输入:
dominoes = [[1, 2], [2, 1], [1, 2], [2, 1]]
输出:6
样例3:
输入:
dominoes = [[3, 3], [3, 3], [3, 3], [3, 3]]
输出:6
二. 思路解析
2.1 问题理解
我们需要计算在给定的多米诺骨牌数组中,有多少对多米诺骨牌是等价的。等价的定义是:两张多米诺骨牌可以通过旋转 0 度或 180 度得到另一张。也就是说,[a, b] 和 [b, a] 是等价的。
2.2 数据结构选择
为了高效地统计每个多米诺骨牌的出现次数,我们可以使用哈希表(HashMap)。哈希表的键可以是一个字符串,表示排序后的多米诺骨牌,值则是该多米诺骨牌出现的次数。
三. 解题步骤
3.1 算法步骤
-
遍历多米诺骨牌数组:
- 对于每个多米诺骨牌,先将其两个数字排序,确保
[a, b]和[b, a]被视为相同的键。 - 将排序后的多米诺骨牌转换为字符串,作为哈希表的键。
- 更新哈希表中该键的计数。
- 对于每个多米诺骨牌,先将其两个数字排序,确保
-
计算等价对数:
- 对于哈希表中的每个键,如果一个多米诺骨牌出现了
count次,那么等价对数为count * (count - 1) / 2。这是因为从count个相同的骨牌中选择两个的组合数为C(count, 2),即count * (count - 1) / 2。
- 对于哈希表中的每个键,如果一个多米诺骨牌出现了
-
返回结果:
- 将所有等价对数相加,得到最终的结果。
3.2 复杂度分析
- 时间复杂度:O(n log n),其中 n 是多米诺骨牌的数量。排序每个多米诺骨牌需要 O(log n) 的时间,遍历所有多米诺骨牌需要 O(n) 的时间。
- 空间复杂度:O(n),用于存储哈希表。
四. Code
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static int solution(int[][] dominoes) {
// 使用哈希表来统计每个多米诺骨牌的出现次数
Map<String, Integer> countMap = new HashMap<>();
// 遍历每个多米诺骨牌
for (int[] domino : dominoes) {
// 将多米诺骨牌的两个数字排序,确保 [a, b] 和 [b, a] 被视为相同的键
Arrays.sort(domino);
// 将多米诺骨牌转换为字符串作为键
String key = Arrays.toString(domino);
// 更新哈希表中的计数
countMap.put(key, countMap.getOrDefault(key, 0) + 1);
}
int pairs = 0;
// 计算等价对数
for (int count : countMap.values()) {
// 如果一个多米诺骨牌出现了 count 次,那么等价对数为 count * (count - 1) / 2
pairs += count * (count - 1) / 2;
}
return pairs;
}
public static void main(String[] args) {
System.out.println(solution(new int[][]{{1, 2}, {2, 1}, {3, 4}, {5, 6}}) == 1);
System.out.println(solution(new int[][]{{1, 2}, {2, 1}, {1, 2}, {2, 1}}) == 6);
System.out.println(solution(new int[][]{{3, 3}, {3, 3}, {3, 3}, {3, 3}}) == 6);
}
}
五. 总结
使用AI进行题解是一种高效且准确的学习辅助工具,能够帮助用户快速理解复杂的算法问题。然而,用户仍需保持独立思考和学习的能力,避免过度依赖AI。通过结合AI的辅助和自身的努力,用户可以更好地提升编程技能和解决问题的能力。