685. 冗余连接 II

685. 冗余连接 II

原题链接:

685. 冗余连接 II

https://leetcode.cn/problems/redundant-connection-ii/description/

完成情况:

解题思路:

java 复制代码
在这里插入代码片

参考代码:

java 复制代码
package 代码随想录.并查集;

import java.util.ArrayList;

public class _685冗余连接II {
    int N_node = 1002;
    int fatherPaths [] ;

    public _685冗余连接II() {
        fatherPaths = new int[N_node];
        //并查集初始化
        for (int i = 0; i < N_node; i++){
            fatherPaths[i] =  i;
        }
    }

    /**
     * 有向图形成输,然后去除掉节点,存在多个 节点则删除掉最后一个节点
     * @param edges
     * @return
     */
    public int[] findRedundantDirectedConnection(int[][] edges) {
        //这次主要是多了一个方向,构造父亲节点,寻根的时候要考虑方向问题
        int [] inDegree = new int[N_node];  //记录入度边
        for (int i = 0;i< edges.length;i++){
            //入度边
            inDegree[edges[i][1]] += 1;
        }
        //找出入度为 2的节点所对应的边,注意要倒序,因为优先返回最后出现在二维数组中的答案
        ArrayList<Integer> twoInDegree = new ArrayList<Integer>();  //注意要重点留意那些有多个入度的边,因为如果只有一个节点的话,你删除掉了那个节点,那么就会导致出现单节点,就无法构成一颗树
        for (int i = edges.length - 1;i>=0;i--){
            if (inDegree[edges[i][1]] == 2){    //只要大于1条边就记录下来
                twoInDegree.add(i);
            }
        }

        //处理图中情况1 和情况2
        //如果有入度为2的节点,那么一定是两条边里删除一个,看看删哪个可以构成树
        if (!twoInDegree.isEmpty()){
            if (isTreeAfterRemoveEdge(edges,twoInDegree.get(0))){
                return edges[twoInDegree.get(0)];
            }
            return edges[twoInDegree.get(1)];
        }

        //明确没有入度大于2的情况了,那么一定有有向环,找到构成环的边返回就可以了
        if (!twoInDegree.isEmpty()){
            if (isTreeAfterRemoveEdge(edges,twoInDegree.get(0))){
                return edges[twoInDegree.get(0)];
            }
            return edges[twoInDegree.get(1)];
        }

        //明确没有入度为2的情况,那么 一定有有向环,找到构成环的边返回就可以了
        return getRemoveEdge(edges);
    }

    /**
     * 在有向图里找到删除的那条边,使其变成树
     * @param edges
     * @return 要删除的边
     */
    private int[] getRemoveEdge(int[][] edges) {
        initFatherPath();
        for (int i = 0; i < edges.length; i++) {
            if (sameEdge(edges[i][0], edges[i][1])){    //构成 有向环了,就删除要删除的边
                return edges[i];
            }
            joinEdge(edges[i][0],edges[i][1]);
        }
        return null;
    }

    /**
     *
     * @param edgeA
     * @param edgeB
     */
    private void joinEdge(int edgeA, int edgeB) {
        edgeA = fatherPaths[edgeA];
        edgeB = fatherPaths[edgeB];
        if (edgeA == edgeB) return;
        fatherPaths[edgeB] = edgeA; //     A -> B
    }

    /**
     *
     * @param edgeA
     * @param edgeB
     * @return
     */
    private boolean sameEdge(int edgeA, int edgeB) {
        edgeA = fatherPaths[edgeA];
        edgeB = fatherPaths[edgeB];
        return edgeB == edgeA;
    }

    /**
     *
     */
    private void initFatherPath() {
        //并查集初始化
        for (int i =0;i<N_node;++i){
            fatherPaths[i] = i;
        }
    }

    /**
     * 删一条边之后判断是不是树
     * @param edges
     * @param deleteEdge 要删除的边
     * @return  true: 是树, false: 不是树
     */
    private boolean isTreeAfterRemoveEdge(int[][] edges, int deleteEdge) {
        initFatherPath();
        for (int i = 0; i < edges.length;i++){
            if (i == deleteEdge)    continue;
            if (sameEdge(edges[i][0],edges[i][1])){ //构成有向环了,一定不是树
                return false;
            }
            joinEdge(edges[i][0],edges[i][1]);
        }
        return true;
    }
}

错误经验吸取

相关推荐
爱吃喵的鲤鱼4 分钟前
linux进程的状态之环境变量
linux·运维·服务器·开发语言·c++
易云码19 分钟前
信息安全建设方案,网络安全等保测评方案,等保技术解决方案,等保总体实施方案(Word原件)
数据库·物联网·安全·web安全·低代码
newxtc25 分钟前
【客观理性深入讨论国产中间件及数据库-科创基础软件】
数据库·中间件·国产数据库·国产中间件·科创
懒惰才能让科技进步26 分钟前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝
水月梦镜花27 分钟前
redis:list列表命令和内部编码
数据库·redis·list
DARLING Zero two♡30 分钟前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
Gu Gu Study32 分钟前
【用Java学习数据结构系列】泛型上界与通配符上界
java·开发语言
Ni-Guvara40 分钟前
函数对象笔记
c++·算法
芊寻(嵌入式)1 小时前
C转C++学习笔记--基础知识摘录总结
开发语言·c++·笔记·学习
一颗松鼠1 小时前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript