LeetCode 684.冗余連接 - JavaScript

??Blog :《LeetCode 684.冗余連接 - JavaScript》

題目描述:在本問題中, 樹指的是一個連通且無環(huán)的無向圖。

輸入一個圖,該圖由一個有著 N 個節(jié)點 (節(jié)點值不重復 1, 2, ..., N) 的樹及一條附加的邊構(gòu)成。附加的邊的兩個頂點包含在 1 到 N 中間,這條附加的邊不屬于樹中已存在的邊。

結(jié)果圖是一個以邊組成的二維數(shù)組。每一個邊的元素是一對[u, v] ,滿足 u < v,表示連接頂點 u 和 v 的無向圖的邊。

返回一條可以刪去的邊,使得結(jié)果圖是一個有著 N 個節(jié)點的樹。如果有多個答案,則返回二維數(shù)組中最后出現(xiàn)的邊。答案邊 [u, v] 應滿足相同的格式 u < v。

題目分析

題目很長,通俗來說就是有一棵樹,然后輸入中給出了這顆樹中的所有節(jié)點連線,除此之外還多給了一條。這條多出來的邊會導致不符合樹的定義。例如在下面的例子中,多出來的[1, 4]這條邊形成了環(huán):

輸入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
輸出: [1,4]
解釋: 給定的無向圖為:
5 - 1 - 2
    |   |
    4 - 3

解法 1:并查集(DSU)

對一棵樹來說,有著唯一的根節(jié)點。所有邊[u, v]中的 u 和 v 應該都屬于同一個集合,從形狀上來看,它們都是連接點根節(jié)點。

如果[p, q]是重復邊,那么 p 和 q 之前應該被記錄到了同一集合中。所以每次在加入新邊的時候,檢查集合中是否已經(jīng)包含邊兩邊的節(jié)點即可。

可以使用并查集來描述這種關(guān)系,并且并查集可以快速找到節(jié)點集合以及快速合并 2 個集合。代碼實現(xiàn)如下:

// ac地址:https://leetcode-cn.com/problems/redundant-connection/
// 原文地址:https://xxoo521.com/2020-02-28-redundant-connection/

class UnionFind {
    constructor() {
        this.parent = new Map();
    }

    // 查找元素所在集合
    find(x) {
        while (this.parent.has(x)) {
            x = this.parent.get(x);
        }
        return x;
    }

    // 合并兩個集合
    union(p, q) {
        const rootP = this.find(p);
        const rootQ = this.find(q);
        if (rootP !== rootQ) {
            this.parent.set(this.find(p), this.find(q));
        }
    }
}

/**
 * @param {number[][]} edges
 * @return {number[]}
 */
var findRedundantConnection = function(edges) {
    const uf = new UnionFind();

    for (const edge of edges) {
        const p = edge[0];
        const q = edge[1];
        if (uf.find(p) === uf.find(q)) {
            return [p, q];
        }
        uf.union(p, q);
    }
    return [-1, -1];
};

解法 2: DFS

對于邊[u, v]使用 DFS,檢查 u、v 是否相連。如果可以,則它是重復邊。

拓展思考:為什么不能使用集合(Set)?

在完成并查集的解法后,我又用了 Set 這種數(shù)據(jù)結(jié)構(gòu)來嘗試這題,如下所示:

/**
 * @param {number[][]} edges
 * @return {number[]}
 */
var findRedundantConnection = function(edges) {
    const set = new Set();
    for (const edge of edges) {
        if (set.has(edge[0]) && set.has(edge[1])) {
            return edge;
        }
        set.add(edge[0]).add(edge[1]);
    }
    return [-1, -1];
};

結(jié)果自然是沒有 ac。錯誤用例是:

輸入:[[3,4],[1,2],[2,4],[3,5],[2,5]]
錯誤輸出:[2,4]

錯誤原因是:Set 不能保證里面的節(jié)點都屬于同一個「連通分量」。例如 3、4 是連通的,1、2 是連通的,但是這是兩個連通分量。

而并查集通過保存節(jié)點的 parent 指向,一直查找,最終查找到的節(jié)點可以視為這個連通分量的根節(jié)點。連通分量中的其他節(jié)點都是指向它的,因此它可以用來標識連通分量。

更多資料

若有錯誤,歡迎指正。若對您有幫助,請給個「關(guān)注+點贊」,您的支持是我更新的動力 ??

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 1)這本書為什么值得看: Python語言描述,如果學的Python用這本書學數(shù)據(jù)結(jié)構(gòu)更合適 2016年出版,內(nèi)容...
    孫懷闊閱讀 12,884評論 0 15
  • 1. 圖的定義和基本術(shù)語 線性結(jié)構(gòu)中,元素僅有線性關(guān)系,每個元素只有一個直接前驅(qū)和直接后繼;樹形結(jié)構(gòu)中,數(shù)據(jù)元素(...
    yinxmm閱讀 5,654評論 0 3
  • 目錄 1.圖的表示 2.廣度優(yōu)先搜索 3.深度優(yōu)先搜索——本質(zhì)等同于回溯 4.拓撲排序 5.強連通分量 1.圖的表...
    王偵閱讀 4,482評論 0 8
  • https://zh.visualgo.net/graphds 淺談圖形結(jié)構(gòu)https://zh.visualgo...
    狼之獨步閱讀 4,417評論 0 0
  • 目錄 1.基本圖算法參見基本的圖算法參見深度優(yōu)先搜索和廣度優(yōu)先搜索專題 2.最小生成樹——無向圖參見最小生成樹 3...
    王偵閱讀 1,745評論 0 1

友情鏈接更多精彩內(nèi)容