LCA 類問題
-
LCA 類問題是二叉樹的高頻問題之一;
-
有隻給 root 的;
-
還有不給 root 給 parent pointer 的。
-
想面 FB,最好把各種二叉樹問題的 recursion / iteration 還有 root / parent pointer 的寫法都練熟才行,只 AC 是不夠的。
下面這種向哪裏走的問題,直接用尾遞歸解決。不要想遍歷。
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return root;
if(root.val > p.val && root.val > q.val)
return lowestCommonAncestor(root.left, p, q);
if(root.val < p.val && root.val < q.val)
return lowestCommonAncestor(root.right, p, q);
return root;
}
}
因爲是尾遞歸,顯而易見的改法是用 while循環省去遞歸佔用的系統棧空間;
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
while(root != null){
if(root.val > p.val && root.val > q.val) root = root.left;
else if(root.val < p.val && root.val < q.val) root = root.right;
else return root;
}
return root;
}
}
時間複雜度 O(n),相對於每個 node 來講,只會被函數調用和計算一次。
另一種時間複雜度的分析方式是,這題的遞歸結構是個 post-order traversal,遍歷的複雜度當然是 O(n).
拿到樹的題目,先想遞歸結構是什麼,再想end condition.
想到這,迭代的寫法也比較明顯了,寫個 post-order traversal 就行。
public class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null || root == q || root == p) return root;
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right, p, q);
if(left != null && right != null) return root;
else return (left == null) ? right : left;
}
}
想到這,另外一種思路就是使用HashMap + Set