题目地址:
https://www.lintcode.com/problem/444/
要求设计一个数据结构,可以做如下两个操作:
1、void addEdge(int a, int b)
在
a
a
a与
b
b
b两个点之间连边;
2、bool isValidTree()
问当前的图是否是一棵树。
由于不知道 a a a和 b b b的取值范围,可以采用离散化的方式,动态开点。总体思路是并查集。询问的时候只需要看一下是否集合个数是 1 1 1并且没有环,可以用一个变量记录集合个数,另一个变量记录是否有环。代码如下:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Solution {
List<Integer> p;
Map<Integer, Integer> map;
// group是集合个数
int idx, group;
// isValid记录是否无环
boolean isValid;
public Solution() {
p = new ArrayList<>();
map = new HashMap<>();
isValid = true;
}
int find(int x) {
if (x != p.get(x)) {
p.set(x, find(p.get(x)));
}
return p.get(x);
}
void union(int x, int y) {
int px = find(x), py = find(y);
if (px == py) {
// 有环了,标记一下
isValid = false;
return;
}
p.set(px, py);
group--;
}
/**
* @param a: the node a
* @param b: the node b
* @return: nothing
*/
public void addEdge(int a, int b) {
// write your code here
// 动态开点
if (!map.containsKey(a)) {
group++;
p.add(idx);
map.put(a, idx++);
}
if (!map.containsKey(b)) {
group++;
p.add(idx);
map.put(b, idx++);
}
int x = map.get(a), y = map.get(b);
union(x, y);
}
/**
* @return: check whether these edges make up a valid tree
*/
public boolean isValidTree() {
// write your code here
return isValid && group == 1;
}
}
加边时间复杂度 O ( log ∗ n ) O(\log ^*n) O(log∗n), n n n是已经加的点的个数,查询时间 O ( 1 ) O(1) O(1),空间 O ( n ) O(n) O(n)。