LeetCode_BinaryTree_1129. Shortest Path with Alternating Colors 颜色交替的最短路径【BFS求最短路径】【java】【中等】

一,题目描述

英文描述

You are given an integer n, the number of nodes in a directed graph where the nodes are labeled from 0 to n - 1. Each edge is red or blue in this graph, and there could be self-edges and parallel edges.

You are given two arrays redEdges and blueEdges where:

redEdges[i] = [ai, bi] indicates that there is a directed red edge from node ai to node bi in the graph, and
blueEdges[j] = [uj, vj] indicates that there is a directed blue edge from node uj to node vj in the graph.
Return an array answer of length n, where each answer[x] is the length of the shortest path from node 0 to node x such that the edge colors alternate along the path, or -1 if such a path does not exist.

中文描述

在一个有向图中,节点分别标记为 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。

示例与说明

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/shortest-path-with-alternating-colors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二,解题思路

由于是红蓝交替、蓝红交替都可以,所以可以想象有一个虚拟的节点-1指向0:

如果-1=》0为红色路径,那么0=》下一个节点就要选择蓝色路径

否则正好相反。

由于是求从0开始的最短路径,所以BFS最合适不过了,每次可以得到一层的结果,需要注意两点:

  • 对遍历过的节点,要添加对应的标记,如lastColor为red,需要标记red路径已经使用过,再次遍历到该节点时,需要跳过;
  • 每遍历完一层,需要变换颜色(BFS层次遍历,需要记录当前队列元素数目,这样就可以每次遍历一层的节点);

三,AC代码

Java

import java.util.*;
class Solution {
    public int[] shortestAlternatingPaths(int n, int[][] redEdges, int[][] blueEdges) {
        int[] ans = new int[n];
        for (int i = 0; i < n; i++) ans[i] = Integer.MAX_VALUE;;

        Map<Integer, List<Integer>> redNext = new HashMap<>();
        Map<Integer, List<Integer>> blueNext = new HashMap<>();
        for (int i = 0; i < redEdges.length; i++) {
            if (!redNext.containsKey(redEdges[i][0])) {
                redNext.put(redEdges[i][0], new ArrayList<>());
            }
            List<Integer> list = redNext.get(redEdges[i][0]);
            list.add(redEdges[i][1]);
        }

        for (int i = 0; i < blueEdges.length; i++) {
            if (!blueNext.containsKey(blueEdges[i][0])) {
                blueNext.put(blueEdges[i][0], new ArrayList<>());
            }
            List<Integer> list = blueNext.get(blueEdges[i][0]);
            list.add(blueEdges[i][1]);
        }

        // false: blue指向当前节点, true: red指向当前节点
        bfs(redNext, blueNext, true, ans);
        bfs(redNext, blueNext, false, ans);

        for (int i = 0; i < n; i++) {
            if (ans[i] == Integer.MAX_VALUE) {
                ans[i] = -1;
            }
        }

        return ans;
    }
    // false: blue指向当前节点, true: red指向当前节点
    public void bfs (Map<Integer, List<Integer>> redNext, Map<Integer, List<Integer>> blueNext, boolean lastColor, int[] ans) {
        int n = ans.length;
        boolean[] redVisited = new boolean[n];
        boolean[] blueVisited = new boolean[n];
        Queue<Integer> queue = new LinkedList<>();
        queue.offer(0);
        int step = 0;
        if (lastColor) redVisited[0] = true;
        else blueVisited[0] = true;
        while (!queue.isEmpty()) {
            int size = queue.size();
            while (size-- != 0) {
                int node = queue.peek();
                ans[node] = Math.min(ans[node], step);
                queue.poll();
                // 红色指向当前节点
                if (lastColor && blueNext.containsKey(node)) {
                    for (int num : blueNext.get(node)) {
                        if (!blueVisited[num]) {
                            queue.add(num);
                            blueVisited[num] = true;

                        }
                    }
                }
                // 蓝色指向当前节点
                else if (!lastColor && redNext.containsKey(node)) {
                    for (int num : redNext.get(node)) {
                        if (!redVisited[num]) {
                            queue.add(num);
                            redVisited[num] = true;

                        }
                    }
                }
            }
            lastColor = !lastColor;//  !!!
            step++;
        }
    }
}

四,解题过程

第一搏

这是一次面试的时候遇到的题目,当时没想到用BFS如何处理,一直陷入在DFS如何解决重复遍历同一节点的问题,虽然面试官提示用BFS,但是仍没有领悟到关键o( ̄┰ ̄*)ゞ

第二搏

红蓝交替、蓝红交替都算数,所以要走两遍BFS。。。于是将其抽离为一个单独的方法,注意颜色的切换

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值