当前位置: 首页 > article >正文

LeetCode 684.冗余连接:拓扑排序+哈希表(O(n)) 或 并查集(O(nlog n)-O(nα(n)))

【LetMeFly】684.冗余连接:拓扑排序+哈希表(O(n)) 或 并查集(O(nlog n)-O(nα(n)))

力扣题目链接:https://leetcode.cn/problems/redundant-connection/

树可以看成是一个连通且 无环 的 无向 图。

给定往一棵 n 个节点 (节点值 1~n) 的树中添加一条边后的图。添加的边的两个顶点包含在 1n 中间,且这条附加的边不属于树中已存在的边。图的信息记录于长度为 n 的二维数组 edges ,edges[i] = [ai, bi] 表示图中在 aibi 之间存在一条边。

请找出一条可以删去的边,删除后可使得剩余部分是一个有着 n 个节点的树。如果有多个答案,则返回数组 edges 中最后出现的那个。

 

示例 1:

输入: edges = [[1,2], [1,3], [2,3]]
输出: [2,3]

示例 2:

输入: edges = [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]

 

提示:

  • n == edges.length
  • 3 <= n <= 1000
  • edges[i].length == 2
  • 1 <= ai < bi <= edges.length
  • ai != bi
  • edges 中无重复元素
  • 给定的图是连通的 

方法一:拓扑排序(哈希表)

记录每个点的度,使用拓扑排序的思想,每次将度为1的节点所连的边移除。

最后剩下的点就是“环”中的点,将这些点放入哈希表中。

倒叙遍历“边”,第一条两个节点都出现在哈希表中的边即为所求。

  • 时间复杂度 O ( n ) O(n) O(n)
  • 空间复杂度 O ( n ) O(n) O(n)

AC代码

C++
class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        vector<int> degree(edges.size() + 1);
        vector<vector<int>> graph(edges.size() + 1);
        for (vector<int>& edge : edges) {
            degree[edge[0]]++;
            degree[edge[1]]++;
            graph[edge[0]].push_back(edge[1]);
            graph[edge[1]].push_back(edge[0]);
        }
        queue<int> q;
        for (int i = 1; i <= edges.size(); i++) {
            if (degree[i] == 1) {
                q.push(i);
            }
        }
        while (q.size()) {
            int thisNode = q.front();
            q.pop();
            for (int nextNode : graph[thisNode]) {
                degree[nextNode]--;
                if (degree[nextNode] == 1) {
                    q.push(nextNode);
                }
            }
        }
        unordered_set<int> reservedNodes;
        for (int i = 1; i <= edges.size(); i++) {
            if (degree[i] > 1) {
                reservedNodes.insert(i);
            }
        }
        // for (vector<vector<int>>::iterator it = edges.rbegin(); it != edges.rend(); it++)
        for (int i = edges.size() - 1; i >= 0; i--) {
            if (reservedNodes.count(edges[i][0]) && reservedNodes.count(edges[i][1])) {
                return edges[i];
            }
        }
        return {};  // FAKE RETURN
    }
};

方法二:并查集

使用并查集将每条边的两个顶点加入同一个集合中,第一条两个顶点已经在一个集合中的边即为所求(加上这条边后就形成了环)。

  • 时间复杂度 O ( n log ⁡ n ) O(n\log n) O(nlogn),平均为 O ( n α ( n ) ) O(n\alpha(n)) O(nα(n))(接近 O ( n ) O(n) O(n)
  • 空间复杂度 O ( n ) O(n) O(n)

AC代码

C++
class Solution {
private:
    vector<int> fa;

    int find(int x) {
        if (fa[x] != x) {
            fa[x] = find(fa[x]);
        }
        return fa[x];
    }

    void union_(int x, int y) {
        fa[find(x)] = find(y);
    }
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        fa.resize(edges.size() + 1);
        for (int i = 1; i <= edges.size(); i++) {
            fa[i] = i;
        }
        // for (vector<int>& edge : edges) {
        //     union_(edge[0], edge[1]);
        // }
        // for (int i = edges.size() - 1; i > 0; i--) {
        //     if (find(edges[i][0]) == find(edges[i][1])) {
        //         return edges[i];
        //     }
        // }
        for (vector<int>& edge : edges) {
            if (find(edge[0]) == find(edge[1])) {
                return edge;
            } else {
                union_(edge[0], edge[1]);
            }
        }
        return {};  // FAKE RETURN
    }
};
Python
from typing import List

class Solution:
    def union(self, x: int, y: int) -> None:
        self.fa[self.find(x)] = self.find(y)
    
    def find(self, x: int) -> int:
        if self.fa[x] != x:
            self.fa[x] = self.find(self.fa[x])
        return self.fa[x]

    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        self.fa = [i for i in range(len(edges) + 1)]
        for x, y in edges:
            if self.find(x) == self.find(y):
                return [x, y]
            else:
                self.union(x, y)
        return []  # FAKE RETURN

Java
class Solution {
    private int[] fa;

    private int find(int x) {
        if (fa[x] != x) {
            fa[x] = find(fa[x]);
        }
        return fa[x];
    }

    private void union(int x, int y) {
        fa[find(x)] = find(y);
    }

    public int[] findRedundantConnection(int[][] edges) {
        fa = new int[edges.length + 1];
        for (int i = 1; i <= edges.length; i++) {
            fa[i] = i;
        }
        for (int[] edge : edges) {
            if (find(edge[0]) == find(edge[1])) {
                return edge;
            } else {
                union(edge[0], edge[1]);
            }
        }
        return new int[0];
    }
}
Go
package main

func find(fa []int, x int) int {
    if fa[x] != x {
        fa[x] = find(fa, fa[x])
    }
    return fa[x]
}

func union(fa []int, x int, y int) {
    fa[find(fa, x)] = find(fa, y)
}

func findRedundantConnection(edges [][]int) []int {
    fa := make([]int, len(edges) + 1)
    for th, _ := range fa {
        fa[th] = th
    }
    for _, edge := range edges {
        if find(fa, edge[0]) == find(fa, edge[1]) {
            return edge
        } else {
            union(fa, edge[0], edge[1])
        }
    }
    return nil
}

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

Tisfy:https://letmefly.blog.csdn.net/article/details/143464726

今晚(20241102晚10:30)这会儿api.github.com似乎出了点问题,国内外都访问不到X_X


http://www.kler.cn/a/378434.html

相关文章:

  • 解决方案 | 部署更快,自动化程度高!TOSUN同星线控底盘解决方案
  • 读数据工程之道:设计和构建健壮的数据系统28数据服务常见关注点
  • 设计模式之结构型模式---装饰器模式
  • C++11新特性之Lambda函数
  • 网络安全法详细介绍——爬虫教程
  • SQL 常用语句
  • 使用GetX实现GetPage中间件
  • WordPress在windows下安装
  • 【Git】从 GitHub 仓库中移除误提交的 IntelliJ IDEA 配置文件夹 .idea 并将其添加到 .gitignore 文件中
  • MyBatis-Plus快速入门:从安装到第一个Demo
  • React Native 0.76 重大更新:新架构全面启用
  • 基于Python的自然语言处理系列(47):DistilBERT:更小、更快、更省、更轻的BERT版本
  • C++编程法则365天一天一条(344)理解std::optional的设计初衷
  • 数据库日志分析 ApexSQLLog
  • 基于SSM+VUE历史车轮网站JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解
  • Zypher Network:全栈式 Web3 游戏引擎,服务器抽象叙事的领导者
  • 2.若依vue表格数据根据不同状态显示不同颜色style
  • 【Flask框架】10、Flask项目拆分规范
  • 论文略读:Self-Knowledge Guided Retrieval Augmentation for Large Language Models
  • SQL之排名窗口函数RANK()、ROW_NUMBER()、DENSE_RANK() 和 NTILE() 的区别(SQL 和 Hive SQL 都支持)
  • C++ 多态原理
  • 提升教育质量:SpringBoot在线试题库系统
  • 微服务保护相关面试题
  • OpenAI官方提供撰写提示词最佳实践
  • Python3 No module named ‘pymysql‘
  • 【解决方案】微信小程序如何使用 ProtoBuf 进行 WebSocket 通信