原题地址(简单)
方法1—哈希表存储每个结点的父节点
思路
- 用一张哈希表存储每个结点的父节点,具体方法是递归遍历整棵树来填充哈希表;
- 再根据哈希表算出两个结点
pq到根节点的距离,假定为p_lenq_len - 算出两者距离的差值
pre_len,让远的那个先向上走pre_len步 - 然后再一起向上走,直到相遇。
代码
class Solution {public:unordered_map<TreeNode*, TreeNode*> parents;TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {//先从两节点向上遍历至根节点,记下步数,再让步数大的那个先走,然后再同时走。//定义哈希表存储每个节点的父节点parents[root] = nullptr;setParents(root);int p_steps = calStep(p);int q_steps = calStep(q);int pre_steps = p_steps - q_steps;while(pre_steps > 0) {p = parents[p];pre_steps--;}while(pre_steps < 0) {q = parents[q];pre_steps++;}while(1) {if(p == q) break;p = parents[p];q = parents[q];}return p;}void setParents(TreeNode* root) {if(!root) return;if(root->left){parents[root->left] = root;setParents(root->left);}if(root->right){parents[root->right] = root;setParents(root->right);}}int calStep(TreeNode* t) {int ans = 0;while(parents[t]) {ans++;t = parents[t];}return ans;}};
方法二—vector存储两结点的路径
这个方法要比第一个方法简单些,运行速度也更快
思路
- 用递归遍历树,根据二叉搜索树的性质,可以很容易、很快速的得到根节点到某个结点的路径,存储在
vector中。所以记两节点路径为p_pathq_path - 然后用一个循环从后向前遍历两节点的路径
vector,直到相遇。而遍历的长度应为min(p_path.size(), q_path.size())
代码
class Solution {public:TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {vector<TreeNode*> p_path, q_path;addPath(root, p, p_path);addPath(root, q, q_path);int len = min(p_path.size(), q_path.size());int i = len - 1;for(; i >= 0; i--) {if(p_path[i] == q_path[i]) return p_path[i];}return p_path[i];}void addPath(TreeNode* root, TreeNode* t, vector<TreeNode*>& path) {path.emplace_back(root);if(root == t) return;if(root->val > t->val) addPath(root->left, t, path);else addPath(root->right, t, path);}};
