The nearest common ancestor of a binary tree

Keywords: Java github network

My LeetCode: https://leetcode-cn.com/u/ituring/

My LeetCode source code [GitHub]: https://github.com/izhoujie/Algorithmcii

The nearest common ancestor of a binary tree

subject

Given a binary tree, find the nearest common ancestor of two specified nodes in the tree.

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 tree: root = [3,5,1,6,2,0,8,null,null,7,4]

Example 1:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
 Output: 3
 Explanation: the most recent common ancestor of node 5 and node 1 is node 3.

Example 2:

Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
 Output: 5
 Explanation: the most recent common ancestor of nodes 5 and 4 is node 5. Because by definition the nearest 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 tree.

Source: LeetCode
Link: https://leetcode-cn.com/problems/lowest-common-ancestor-of-a-binary-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 - recursive judgment

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 6:00:19 p.m., March 7, 2010 
 * @Description: 236. The nearest common ancestor of a binary tree
 *
 */
public class LeetCode_0236 {

}

//  Definition for a binary tree node.
class TreeNode_0236 {
	int val;
	TreeNode_0236 left;
	TreeNode_0236 right;

	TreeNode_0236(int x) {
		val = x;
	}
}

class Solution_0236 {
	/**
	 * @author: ZhouJie
	 * @date: 2020 6:20:23 p.m., March 7, 2010 
	 * @param: @param root
	 * @param: @param p
	 * @param: @param q
	 * @param: @return
	 * @return: TreeNode_0236
	 * @Description: 1-Recursive verification, took a detour
	 *
	 */
	public TreeNode_0236 lowestCommonAncestor_1(TreeNode_0236 root, TreeNode_0236 p, TreeNode_0236 q) {
		if (root == null) {
			return null;
		} else if (root == p || root == q) {
			return root;
		} else {
			boolean f1 = check(root.left, p);
			boolean f2 = check(root.right, q);
			if (f1 == !f2) {
				if (f1) {
					return lowestCommonAncestor_1(root.left, p, q);
				} else {
					return lowestCommonAncestor_1(root.right, p, q);
				}
			} else {
				return root;
			}
		}
	}

	private boolean check(TreeNode_0236 root, TreeNode_0236 node) {
		if (root == null) {
			return false;
		} else if (root == node) {
			return true;
		} else {
			return check(root.left, node) || check(root.right, node);
		}
	}

	/**
	 * @author: ZhouJie
	 * @date: 2020 6:20:19 p.m., March 7, 2010 
	 * @param: @param root
	 * @param: @param p
	 * @param: @param q
	 * @param: @return
	 * @return: TreeNode_0236
	 * @Description: 2-Or recursion, after optimization;
	 * 				Understanding: if it is on both sides, the left and right of the recursion are not null, and root is returned. Otherwise, whoever is not null means who must be the ancestor node
	 *
	 */
	public TreeNode_0236 lowestCommonAncestor_2(TreeNode_0236 root, TreeNode_0236 p, TreeNode_0236 q) {
		if (root == null || root == p || root == q) {
			return root;
		} else {
			TreeNode_0236 left = lowestCommonAncestor_2(root.left, p, q);
			TreeNode_0236 right = lowestCommonAncestor_2(root.right, p, q);
			if (left == null) {
				return right;
			} else if (right == null) {
				return left;
			} else {
				return root;
			}
		}
	}

}

Posted by Confusion101 on Tue, 12 May 2020 01:49:51 -0700