LeetCode-684. Redundant Connection [C++][Java]

LeetCode-684. Redundant ConnectionLevel up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.https://leetcode.com/problems/redundant-connection/

In this problem, a tree is an undirected graph that is connected and has no cycles.

You are given a graph that started as a tree with n nodes labeled from 1 to n, with one additional edge added. The added edge has two different vertices chosen from 1 to n, and was not an edge that already existed. The graph is represented as an array edges of length n where edges[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the graph.

Return an edge that can be removed so that the resulting graph is a tree of n nodes. If there are multiple answers, return the answer that occurs last in the input.

Example 1:

Input: edges = [[1,2],[1,3],[2,3]]
Output: [2,3]

Example 2:

Input: edges = [[1,2],[2,3],[3,4],[1,4],[1,5]]
Output: [1,4]

Constraints:

  • n == edges.length
  • 3 <= n <= 1000
  • edges[i].length == 2
  • 1 <= ai < bi <= edges.length
  • ai != bi
  • There are no repeated edges.
  • The given graph is connected.

【C++】

1. 并查集

class UF {
    vector<int> id, size;
public:
    UF(int n): id(n), size(n, 1) {
        iota(id.begin(), id.end(), 0); // iota函数可以把数组初始化为0到n-1
    }
    int find(int p) {
        while (p != id[p]) {
            id[p] = id[id[p]]; // 路径压缩,使得下次查找更快
            p = id[p];
        }
        return p;
    }
    void connect(int p, int q) {
        int i = find(p), j = find(q);
        if (i != j) {
        // 按秩合并:每次合并都把深度较小的集合合并在深度较大的集合下面
            if (size[i] < size[j]) {
                id[i] = j;
                size[j] += size[i];
            } else {
                id[j] = i;
                size[i] += size[j];
            }
        }
    }
    bool isConnected(int p, int q) {
        return find(p) == find(q);
    }
};

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = edges.size();
        UF uf(n + 1);
        for (auto e: edges) {
            int u = e[0], v = e[1];
            if (uf.isConnected(u, v)) {return e;}
            uf.connect(u, v);
        }
        return vector<int>{-1, -1};
    }
};

2. 粗暴循环打法

class Solution {
public:
    vector<int> findRedundantConnection(vector<vector<int>>& edges) {
        int n = 0;
        for(const auto &e : edges) {
            n = max(e[0]+1, n);
            n = max(e[1]+1, n);
        }
        parent_ = vector<int>(n);
        for(int i = 0; i < n; ++i) parent_[i] = i;
        for(auto it = edges.begin(); it != edges.end(); ++it) {
            const auto &e = *it;
            if(GetParent(e[0]) == GetParent(e[1])) {
                  if(e[0] < e[1]) return {e[0], e[1]};
                  else return {e[1], e[0]};
            }
            parent_[GetParent(e[0])] = GetParent(e[1]);
        }
        return {};
    }
private:
    int GetParent(int x) {
        if(parent_[x] != x) parent_[x] = GetParent(parent_[x]);
        return parent_[x];
    }
    vector<int> parent_;
};

【Java】

class Solution {
    private int[] parent_;
    public int[] findRedundantConnection(int[][] edges) {
        int n = 0;
        for(int[] e : edges) {
            n = Math.max(e[0]+1, n);
            n = Math.max(e[1]+1, n);
        }
        parent_ = new int[n];
        for(int i = 0; i < n; ++i) parent_[i] = i;
        for(int[] e : edges) {
            if (GetParent(e[0]) == GetParent(e[1])) {
                  if(e[0] < e[1]) return new int[]{e[0], e[1]};
                  else return new int[]{e[1], e[0]};
            }
            parent_[GetParent(e[0])] = GetParent(e[1]);
        }
        return new int[]{};
    }

    private int GetParent(int x) {
        if(parent_[x] != x) parent_[x] = GetParent(parent_[x]);
        return parent_[x];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贫道绝缘子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值