LeetCode 684. 冗餘連接(樹+冗餘邊成環)並查集求冗餘邊

冗餘連接

運行時間排名不太好。
大體思路:
①先用並查集求出環中的某一個點,依次作爲搜索的起點:
成環的要求:要merge的兩個節點,它們已經在一個並查集裏面了。

ufs.find(y)==ufs.find(x)


用上面求出的根節點作爲搜索起點,dfs遍歷整棵樹。注意不能走回頭路


當再次搜索到根節點的時候,說明成環,立即結束遞歸。


爲了方便最後的查詢(O(log n)),用set記錄下搜索路徑上的點,回溯時,注意刪除。


最後逆序遍歷題給的邊集,若邊的兩個點,都在集合裏,輸出。

整體時間複雜度:
O(nlogn)O(n*logn)

struct UFS{
    int f[1010];
    UFS(){
        for(int i=0;i<1010;i++){
            f[i] = i;
        }
    }
    int find(int x){
        return x==f[x]?x:f[x]=find(f[x]);
    }
    void merge(int x,int y){
        f[find(x)] = find(y);
    }
};
//先用並查集找環裏面的某一個節點
class Solution {
public:
    int graph[1010][1010] = {0};
    int n,root;
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        n = edges.size();
        UFS ufs;
        for(auto edge:edges){
            int x = edge[0];
            int y = edge[1];
            graph[x][y] = graph[y][x] = 1;
            if(ufs.find(y)==ufs.find(x)){
                root = x;
                break;
            }
            ufs.merge(x,y);
        }
        set<int> res;
        dfs(root,0,res);

        // cout<<root<<endl;
        vector<int> ans;
        for(int i=n-1;i>=0;i--){
            auto edge=edges[i];
            int x = edge[0];
            int y = edge[1];
            if(res.count(x) && res.count(y)){
                ans.push_back(min(x,y));
                ans.push_back(max(x,y));
                break;
            }
        }
        return ans;
    }
    bool dfs(int x,int last,set<int>&res){
        // cout<<x<<endl;
        if(x==root && last!=0){
            return true;
        }
        res.insert(x);
        for(int y=1;y<=n;y++){
            if(graph[x][y] && y!=last){
                if(dfs(y,x,res)){
                    return true;
                }
                res.erase(y);
            }
        }
        return false;
    }
};

更爲優雅的做法依次遍歷邊集,如果x,y的代表元已經相同,那麼說明這時候再去merge(x,y),相當於成環。
如果沒有,merge(x,y)。
注:題目要求,若有多解,選擇題給數據中的最後一個數據。
所以,直接順次遍歷就好。

class Solution {
public:
    int f[1010];
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        for(int i=1;i<=edges.size();i++){
            f[i] = i;
        }
        vector<int> ans;
        for(auto edge:edges){
            int x = edge[0];
            int y = edge[1];
            if(find(x)==find(y)){
                ans = edge;
            }else{
                merge(x,y);
            }
        }
        return ans;
    }
    int find(int x){
        return x==f[x]?x:f[x]=find(f[x]);
    }
    void merge(int x,int y){
        f[find(x)] = find(y);
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章