题目来源
这是一个LCA的问题 ,要自己建树比较麻烦。
既然是自己建树,那就自己想怎么建怎么建了,我只建parent pointer就好了,根本不需要child pointer。
用HashMap表示。
找的时候可以先把一个到根的路径找出来放到hashSet里面,再走另一个,第一个遇到的重复的节点就是了。
也可以看谁离根最远,先走最远的那一条路径,然后两个路径一起走,遇到相同的就返回。这样就省了空间。
但是建树的空间还是不能省的 。
public class LCAWords {
Map<String, String> parentMap;
public LCAWords(String[][] words) {
parentMap = new HashMap<>();
for (String[] record : words) {
String p = record[0];
for (int i = 1; i < record.length; i++) parentMap.put(record[i], p);
}
}
public String find(String w1, String w2) {
Set<String> w1Parent = new HashSet<>();
String w1n = w1;
while (w1n != null) {
w1Parent.add(w1n);
w1n = parentMap.get(w1n);
}
while (w2 != null) {
if (w1Parent.contains(w2)) return w2;
w2 = parentMap.get(w2);
}
return null;
}
public String find2(String w1, String w2) {
int n1 = distToParent(w1, parentMap);
int n2 = distToParent(w2, parentMap);
while (n1 > n2) {
w1 = parentMap.get(w1);
n1--;
}
while (n2 > n1) {
w2 = parentMap.get(w2);
n2--;
}
while (!w1.equals(w2)) {
w1 = parentMap.get(w1);
w2 = parentMap.get(w2);
}
return w1;
}
private int distToParent(String w, Map<String, String> parentMap) {
int n = 0;
while (w != null) {
w = parentMap.get(w);
n ++;
}
return n;
}
public static void main(String[] args) {
String[][] words = new String[][] {{"earth", "north america", "south america"},
{"south america", "brazil", "arginta"},
{"north america", "united states", "canada"},
{"united states", "california", "new york"},
{"california", "san francisco", "oakland"}};
String word1 = "california";
String word2 = "oakland";
LCAWords solultion = new LCAWords(words);
Display.myPrint(solultion.find(word1, word2));
Display.myPrint(solultion.find2(word1, word2));
}
}
网友评论