My LeetCode: https://leetcode-cn.com/u/ituring/
My LeetCode source code [GitHub]: https://github.com/izhoujie/Algorithmcii
LeetCode 235. The nearest common ancestor of binary search tree
subject
Given a binary search tree, the nearest common ancestor of two specified nodes in the tree is found.
The definition of the nearest common ancestor in Baidu Encyclopedia is: "for two nodes p and q with root tree T, the nearest common ancestor is represented as a node x, which satisfies that x is the ancestor of p and q and the depth of X is as large as possible (a node can also be its own ancestor)."
For example, given the following binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
Example 1:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 Output: 6 Explanation: the most recent common ancestor of nodes 2 and 8 is 6.
Example 2:
Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 Output: 2 Explanation: the closest common ancestor of node 2 and node 4 is 2, because according to the definition, the closest common ancestor node can be the node itself.
explain:
- The values of all nodes are unique.
- p. q is a different node and exists in a given binary search tree.
Source: LeetCode
Link: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-search-tree
Copyright belongs to the network. For commercial reprint, please contact the official authorization. For non-commercial reprint, please indicate the source.
Solutions to problems
Idea 1 - using the characteristics of binary search tree
The value of the parent node is greater than that of the left subtree node and less than that of the right subtree node;
So the condition of recursion:
- Return directly when root is null;
- If the value of pq is less than the value of root, the ancestor node must be in the left subtree and recursively process the left subtree;
- If the value of pq is greater than the value of root, the ancestor node must be in the right subtree and recursively process the right subtree;
- One of the values of pq is equal to the value of root, which returns root;
Algorithm complexity:
- Time complexity: ${\ color{Magenta}{\Omicron\left(n\right)}}}$
- Spatial complexity: ${\ color{Magenta}{\Omicron\left(logn\right)}}}$
Idea 2 - recursively judge whether root and pq are equal
Thinking analysis: possible situations:
- The current node is one of them, which is returned directly;
- The current node is not one of them;
- The target nodes are scattered in the left and right subtrees of the current node;
- The target node is concentrated in one of the subtrees of the current node;
Recursion is designed according to the above logic:
- Current node is one of the target nodes, return;
- The current node is not one of the target nodes, but the target node is found in the final recursion of the left and right subtrees and scattered in the left and right subtrees (the final return is not null), then the current node is the common ancestor node;
- If the current node is not one of the target nodes, and one of the left and right subtrees returns null, the non null party continues the previous two steps of recursive logic;
Algorithm complexity:
- Time complexity: ${\ color{Magenta}{\Omicron\left(n\right)}}}$
- Spatial complexity: ${\ color{Magenta}{\Omicron\left(logn\right)}} $depth of recursive stack
Algorithm source code example
package leetcode; /** * @author ZhouJie * @date 2020 12:49:27 PM, May 13, 2010 * @Description: 235. The nearest common ancestor of binary search tree * */ public class LeetCode_0235 { } //Definition for a binary tree node. class TreeNode_0235 { int val; TreeNode_0235 left; TreeNode_0235 right; TreeNode_0235(int x) { val = x; } } class Solution_0235 { /** * @author: ZhouJie * @date: 2020 12:51:13 PM, May 13, 2010 * @param: @param root * @param: @param p * @param: @param q * @param: @return * @return: TreeNode_0235 * @Description: 1-The property of binary search tree: the parent node is larger than the left node and smaller than the right node * */ public TreeNode_0235 lowestCommonAncestor_1(TreeNode_0235 root, TreeNode_0235 p, TreeNode_0235 q) { if (root == null) { return root; // If the pq value is greater than the root value, the ancestor node is in the left subtree } else if (root.val > p.val && root.val > q.val) { return lowestCommonAncestor_1(root.left, p, q); // If pq value is less than root value, the ancestor node is in the right subtree } else if (root.val < p.val && root.val < q.val) { return lowestCommonAncestor_1(root.right, p, q); // One of the pq values is equal to the root value } else { return root; } } /** * @author: ZhouJie * @date: 2020 12:51:26 PM, May 13, 2010 * @param: @param root * @param: @param p * @param: @param q * @param: @return * @return: TreeNode_0235 * @Description: 2-Direct recursive verification node; * */ public TreeNode_0235 lowestCommonAncestor_2(TreeNode_0235 root, TreeNode_0235 p, TreeNode_0235 q) { if (root == null || root == p || root == q) { return root; } else { TreeNode_0235 left = lowestCommonAncestor_2(root.left, p, q); TreeNode_0235 right = lowestCommonAncestor_2(root.right, p, q); // One line can be returned, but the readability is poor // return left == null ? right : (right == null ? left : root); if (left == null) { return right; } else if (right == null) { return left; } else { return root; } } } }