1. Root-to-Node Path Intersection
Intuition
Perform standard BST searches from root to p and from root to q, storing the visited nodes in paths pathP and pathQ. Iterate through both lists simultaneously from index 0 until the nodes diverge. The last matching node is the LCA. Takes O(H) time and O(H) auxiliary space to store paths.
When to apply: When path reconstruction is explicitly required for tracing or debugging.
Algorithm
- Find path from root to p, and path from root to q using BST search. The last common node in both paths is the LCA.
#include <iostream>#include <vector> struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}}; class Solution { bool getPath(TreeNode* root, TreeNode* target, std::vector<TreeNode*>& path) { TreeNode* curr = root; while (curr) { path.push_back(curr); if (target->val < curr->val) curr = curr->left; else if (target->val > curr->val) curr = curr->right; else return true; } return false; }public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { std::vector<TreeNode*> pathP, pathQ; getPath(root, p, pathP); getPath(root, q, pathQ); TreeNode* lca = nullptr; int n = std::min(pathP.size(), pathQ.size()); for (int i = 0; i < n; i++) { if (pathP[i] == pathQ[i]) lca = pathP[i]; else break; } return lca; }}; int main() { TreeNode* root = new TreeNode(6); root->left = new TreeNode(2); root->right = new TreeNode(8); root->left->left = new TreeNode(0); root->left->right = new TreeNode(4); root->left->right->left = new TreeNode(3); root->left->right->right = new TreeNode(5); root->right->left = new TreeNode(7); root->right->right = new TreeNode(9); Solution sol; TreeNode* ans = sol.lowestCommonAncestor(root, root->left, root->right); std::cout << "LCA of 2 and 8: " << ans->val << std::endl; return 0;}Time & Space Complexity
- Time complexity:
O(H) where H is tree height - Space complexity:
O(H) to store paths