题目链接
https://www.lintcode.com/problem/1813/
题目描述
描述
给你一系列的边,你需要通过这些边来判断是否能够正确生成二叉树,如果可以生成一个二叉树则返回"successful",不可以则按照错误类型进行返回优先级最高的错误。
在输入中,[“A”,“B”]表示存在一条由节点A指向节点B的边。
你需要判断输入数据是否是正确的。若数据中所有节点的值都是"A"-"Z"之间的长度为1的字符串,则我们认为该数据是正确的。
错误类型的优先级从大到小排序是:“more children”, “repeat edge”, “have cycle”, “more parent”, “input error”。
北大学霸的《算法通关手册.pdf》
微信加【jiuzhang1104】备注【通关】即可参加
pair.length> = 1。
“more children” 表示一个节点有两个以上的节点。
“repeat edge” 表示某一条边出现了多次。
“have cycle” 表示有一个周期。
“more parent” 表示一个节点具有两个父节点或这颗树具有更多根节点。
“input error” 表示输入是不正确的。
样例
示例1:
输入:
pair: [[“A”,“C”],[“A”,“B”],[“A”,“D”]]
输出: “more children”
解释:A 有3个孩子节点,因此你应该返回 “more children” 的错误类型
示例2:
输入:
pair:[[“A”,“C”],[“C”,“A”],[“C”,“B”],[“A”,“C”]]
输出: “repeat edge”
解释: A->C和C->A两条边形成了一个环,但是两条有两条边为A->C,按照错误优先级应该返回“repeat edge”.
java答案
public class Solution {
/**
* @param pair: a list of [parent, children]
* @return: a string of error type
*/
public String constructBinaryTree(List<List<String>> pair) {
UF uf = new UF(); //并查集,主要用于判断并查集集合数,如果大于1,是input error
int size = pair.size();
Map<String, String> issampe = new HashMap<>(); //k:开始点 v:结束点,判断2条边相同
Map<String, String> curparent = new HashMap<>(); //k: 自己 v:父节点 判断自己是否有多个父节点
Map<String, List<String>> childs = new HashMap<>(); //k: 自己 v:父节点 判断自己的子节点是否大于2
for (int i = 0; i < size; i++) {
String p = pair.get(i).get(0);
String c = pair.get(i).get(1);
uf.find(p);
uf.find(c);
uf.union(p, c);
if (!childs.containsKey(p))
childs.put(p, new ArrayList<>());
childs.get(p).add(c);
if (childs.containsKey(p) && childs.get(p).size() > 2) return "more children";
}
for (int i = 0; i < size; i++) {
String p = pair.get(i).get(0);
String c = pair.get(i).get(1);
if (issampe.containsKey(p) && issampe.get(p).equals(c)) return "repeat edge";
issampe.put(p, c);
}
for (int i = 0; i < size; i++) {
String p = pair.get(i).get(0);
String c = pair.get(i).get(1);
String cparent = uf.find(c);
if (c.equals(cparent)) return "have cycle";
}
for (int i = 0; i < size; i++) {
String p = pair.get(i).get(0);
String c = pair.get(i).get(1);
if (curparent.containsKey(c) && !curparent.get(c).equals(p)) return "more parent";
curparent.put(c, p);
}
for (int i = 0; i < size; i++) {
String p = pair.get(i).get(0);
String c = pair.get(i).get(1);
if (!childs.containsKey(p))
childs.put(p, new ArrayList<>());
if (p.length() > 1 || c.length() > 1) return "input error";
}
if (uf.sets > 1) return "input error";
return "successful";
}
static class UF {
Map<String, String> parents = new HashMap<>();
Map<String, Integer> size = new HashMap<>();
Map<Integer, String> help = new HashMap<>();
int sets;
public String find(String x) {
if (!parents.containsKey(x)) {
parents.put(x, x);
size.put(x, 1);
sets++;
}
int hi = 0;
while (!x.equals(parents.get(x))) {
help.put(hi++, x);
x = parents.get(x);
}
for (hi--; hi >= 0; hi--) {
parents.put(help.get(hi), x);
}
return x;
}
public void union(String a, String b) {
String f1 = find(a);
String f2 = find(b);
if (!f1.equals(f2)) {
int s1 = size.get(a);
int s2 = size.get(b);
if (s1 >= s2) {
size.put(f1, s1 + s2);
parents.put(f2, f1);
} else {
size.put(f2, s1 + s2);
parents.put(f1, f2);
}
sets--;
}
}
}
}