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
解题思路:使用hashmap
解题代码:
public static int numEquivDominoPairs(int[][] dominoes) {
Map<String,Integer> map=new HashMap<>();
for (int i=0;i<dominoes.length;i++){
String key=dominoes[i][0]+""+dominoes[i][1];
if (dominoes[i][0]>dominoes[i][1]){
key=dominoes[i][1]+""+dominoes[i][0];
}
if (!map.containsKey(key)){
map.put(key,1);
}else {
map.put(key,map.get(key)+1);
}
}
int count=0;
for (String key:map.keySet()){
int v=map.get(key);
//System.out.println("key:"+v);
if (v>1){
count+=v*(v-1)/2;
}
}
//System.out.println("count:"+count);
return count;
}
1129. 颜色交替的最短路径
在一个有向图中,节点分别标记为 0, 1, …, n-1。这个图中的每条边不是红色就是蓝色,且存在自环或平行边。
red_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的红色有向边。类似地,blue_edges 中的每一个 [i, j] 对表示从节点 i 到节点 j 的蓝色有向边。
返回长度为 n 的数组 answer,其中 answer[X] 是从节点 0 到节点 X 的最短路径的长度,且路径上红色边和蓝色边交替出现。如果不存在这样的路径,那么 answer[x] = -1。
示例 1:
输入:n = 3, red_edges = [[0,1],[1,2]], blue_edges = []
输出:[0,1,-1]
示例 2:
输入:n = 3, red_edges = [[0,1]], blue_edges = [[2,1]]
输出:[0,1,-1]
示例 3:
输入:n = 3, red_edges = [[1,0]], blue_edges = [[2,1]]
输出:[0,-1,-1]
示例 4:
输入:n = 3, red_edges = [[0,1]], blue_edges = [[1,2]]
输出:[0,1,2]
示例 5:
输入:n = 3, red_edges = [[0,1],[0,2]], blue_edges = [[1,0]]
输出:[0,1,1]
解题思路:队列+BFS
解题代码:
public static int[] shortestAlternatingPaths(int n, int[][] red_edges, int[][] blue_edges) {
HashMap<Integer, List<Integer>> redMap = new HashMap<>(), blueMap = new HashMap<>();
Queue<Integer> queue = new LinkedList<Integer>();
int ans[] = new int[n];
int redArrive[] = new int[n];
int blueArrive[] = new int[n];
// 初始化
for(int i = 1;i<n;i++) {
ans[i] = -1;
redArrive[i] = -1;
blueArrive[i] = -1;
}
// 遍历red边
for(int[] edge:red_edges) {
// 将(key)edge[0]即代表源点对象的value放入list
if(redMap.containsKey(edge[0])){
redMap.get(edge[0]).add(edge[1]);
} else {
redMap.put(edge[0], new ArrayList<>());
redMap.get(edge[0]).add(edge[1]);
}
}
// 遍历blue
for(int[] edge:blue_edges) {
if(blueMap.containsKey(edge[0])) {
blueMap.get(edge[0]).add(edge[1]);
} else {
blueMap.put(edge[0], new ArrayList<>());
blueMap.get(edge[0]).add(edge[1]);
}
}
// 操作队列
queue.offer(0);
while(!queue.isEmpty()) {
// 广度优先
BFS(queue, redMap, blueMap, ans, redArrive, blueArrive);
}
return ans;
}
public static void BFS(Queue<Integer> queue, HashMap<Integer,List<Integer>> redMap,HashMap<Integer,List<Integer>> blueMap, int[] ans, int[] redArr, int[] blueArr) {
int node = queue.poll();
System.out.println(node);
// 该node点为源点,在该点红色边已经可达的情况
if(redArr[node]>=0) {
if(blueMap.containsKey(node)) {
List<Integer> target = blueMap.get(node);
System.out.println(target.size());
// 遍历目标点集合,t为目标点,node为源点
for(Integer t : target) {
// 如果t为目标点蓝色不可达或者蓝色目标点可达距离比红色源点可达距离大
if(blueArr[t]<0 || blueArr[t] > redArr[node]+1) {
// 更新最短路径
if(ans[t]== -1 || ans[t] >redArr[node]+1)
ans[t] = redArr[node]+1;
blueArr[t] = redArr[node]+1;
queue.offer(t);
}
System.out.println(node+" - "+t+":");
}
}
}
if(blueArr[node]>=0) {
if(redMap.containsKey(node)) {
List<Integer> target = redMap.get(node);
// System.out.println(target);
for(Integer t : target) {
if(redArr[t]<0 || redArr[t]>blueArr[node]+1){
if(ans[t] == -1 || ans[t] > blueArr[node]+1)
ans[t] = blueArr[node]+1;
redArr[t] = blueArr[node]+1;
queue.offer(t);
}
}
}
}
}