1.タイトルの説明
この問題では、ツリーは、接続されて非循環である無向グラフを指します。
N個のノード(ノード値は1、2、…、Nを繰り返さない)と追加のエッジを持つツリーで構成されるグラフを入力します。追加のエッジの2つの頂点は1とNの間に含まれています。この追加のエッジは、ツリーの既存のエッジに属していません。
結果のグラフは、エッジの2次元配列です。各エッジの要素は[u、v]のペアであり、u <vを満たし、頂点uとvを接続する無向グラフのエッジを示します。
削除可能なエッジを返し、結果のグラフをNノードのツリーにします。複数の回答がある場合、2次元配列の最後のエッジが返されます。回答エッジ[u、v]は、同じフォーマットu <vを満たす必要があります。
输入: [[1,2], [2,3], [3,4], [1,4], [1,5]]
输出: [1,4]
解释: 给定的无向图为:
5 - 1 - 2
| |
4 - 3
第二に、解決策
方法1:チェック
- 初期状態では、各ノードには独自のリーダーがあります。
- 2つのノード間に異なる父親がいる場合は、全体像をたどって、それらをマージします。
- 2つまたは2つのノードが以前にマージされ、同じ引出線が再度チェックされる場合、これらの2つの点によって形成されるエッジが冗長であることを証明します。
public int[] findRedundantConnection(int[][] edges) {
UF uf = new UF(edges.length);
for (int[] edge : edges) {
if (uf.union(edge[0], edge[1]))
return edge;
}
return new int[2];
}
class UF {
int[] id;
UF(int N) {
id = new int[N+50];
for (int i = 0; i < N; i++)
id[i] = i;
}
public int find(int p) {
while (p != id[p]) {
p = id[p];
}
return p;
}
public boolean union(int p, int q) {
int pID = find(p);
int qID = find(q);
if (pID == qID) {
return true;
}
id[pID] = qID;
return false;
}
}
複雑さの分析
- 時間の複雑さ: 、
- スペースの複雑さ: 、
方法2:トポロジカルソート
- トポロジカルソートの開始点は、次数1のすべてのノードです。
- グラフは有向グラフであるため、ほとんどのノードの次数は1より大きいため、これらのノードはリングを形成するのに十分です。リングのエッジは任意に削除でき、グラフの接続性には影響しません。
- 次数1のノードからトポロジーソートを実行し、最終的に逆方向にトラバースすることがわかります
edges
。エッジの2つの頂点の次数が1より大きい場合、2つの頂点がリング上にあることが証明されます削除してください。
質疑応答
- Q1:エッジを最後に逆方向に移動する必要があるのはなぜですか?リング上のすべてのエッジを任意に削除できないのですか?
A1:hh、タイトルは述べています:複数の回答がある場合、2次元配列の最後のエッジが返されます。
class Solution {
List<List<Integer>> g;
int[] in;
boolean[] inq;
public int[] findRedundantConnection(int[][] edges) {
int N = edges.length;
g = new ArrayList<>();
for (int i = 0; i <= N; i++) {
g.add(new ArrayList<>());
}
in = new int[N+1];
inq = new boolean[N+1];
for (int[] e : edges) {
in[e[0]]++; in[e[1]]++;
g.get(e[1]).add(e[0]);
g.get(e[0]).add(e[1]);
}
topo();
for (int i = edges.length-1; i != 0; i--) {
int u = edges[i][0], v = edges[i][1];
if (in[u] > 1 && in[v] > 1)
return edges[i];
}
return new int[2];
}
private void topo() {
Queue<Integer> q = new ArrayDeque<>();
for (int i = 0; i < in.length; i++) {
if (in[i] == 1) {
q.add(i);
inq[i] = true;
}
}
while (!q.isEmpty()) {
int v = q.poll();
inq[v] = false;
for (int nei : g.get(v)) {
if (inq[nei])
continue;
in[nei]--;
if (in[nei] == 1) {
q.add(nei);
inq[nei] = true;
}
}
}
}
}
複雑さの分析
- 時間の複雑さ: 、
- スペースの複雑さ: 、