LeetCode 第 146 场周赛 【等价多米诺骨牌对的数量】【颜色交替的最短路径】

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);
                    }
                }
            }
        }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值