Problem
Bài toán yêu cầu tìm Lowest common Ancestor (LCA) của hai node p và q trong một binary tree. LCA được định nghĩa là node thấp nhất trong cây có cả p và q là hậu duệ (bao gồm trường hợp một node la hậu duệ của chính nó)
“Giao nhau đầu tiên”
Để đi từ gốc đến p hoặc từ gốc đến q, bạn đều phải đi qua node này, và nếu đi sâu hơn thì chỉ còn đi đến p hoặc q riêng lẻ mà thôi, không còn node nào là tổ tiên chung nữa
Approach
Để giải bài toán này, ta sử dụng phương pháp đệ quy với các bước như sau:
Time and space complexity
Solution
1/**
2 * Definition for a binary tree node.
3 * class TreeNode {
4 * val: number
5 * left: TreeNode | null
6 * right: TreeNode | null
7 * constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
8 * this.val = (val===undefined ? 0 : val)
9 * this.left = (left===undefined ? null : left)
10 * this.right = (right===undefined ? null : right)
11 * }
12 * }
13 */
14
15function lowestCommonAncestor(root: TreeNode | null, p: TreeNode | null, q: TreeNode | null): TreeNode | null {
16 if(!root || root === p || root === q) {
17 return root;
18 }
19
20 const left = lowestCommonAncestor(root.left, p, q)
21 const right = lowestCommonAncestor(root.right, p, q)
22
23 if(left && right) {
24 return root;
25 }
26
27 return left || right;
28};Trong thuật toán đệ quy, lần bạn gọi một hàm, chương trình sẽ “ghi nhớ” trạng thái hiện tại (bao gồm các biến cục bộ, vị trí thực thi….) vào ngăn xếp (call stack).
Khi hàm con hoàn thành (tức là gặp lệnh return ), nó sẽ trả kết quả về cho hàm cha đã gọi nó. Quá trình này gọi là “quay lại” (return back hoặc unwind recursion)
Bạn không cần phải viết code "quay lại" vì đây là cách mà mọi hàm đệ quy (và cả hàm thông thường) hoạt động trong mọi ngôn ngữ lập trình hiện đại.
Áp dụng vào thuật toán LCA