# Code Capriccio record: binary tree (Part II)

Posted by plouka on Sun, 06 Feb 2022 19:21:09 +0100

# 236. Nearest common ancestor of binary tree

Title Description:

Train of thought analysis:
Anyway, I'm still confused about recursion... More practice can only be. The thought of boss Carl can still be understood. It's really unexpected when he did it himself.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//We call the current method as a recursive function (post order traversal)
//As soon as the method comes in, we judge whether it is p and q we want, or null
//If it is one of these cases, we will return the current result upward
if(root == p || root == q || root == null) return root;
//Recursively look up the left tree and receive the result with a left pointer
TreeNode left = lowestCommonAncestor(root.left,p,q);
//Recursively look up the right tree and receive the result with a right pointer
TreeNode right = lowestCommonAncestor(root.right,p,q);

//If left and right are not empty, it means that the current node is the nearest common ancestor traced back
if(left != null && right != null) return root;
//If left is empty and right is not empty, it means it is found in the right tree
//vice versa
if(left == null && right != null) return right;
else if(left != null && right == null) return left;
else {//If both are empty, it means that the nearest common ancestor has not been found
return null;
}
}
}
```

# 235. Nearest common ancestor of binary search tree

Title Description:

Train of thought analysis:
The binary search tree is also a binary tree, so we can use the backtracking solution of the binary search tree just now. It's the same:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/

class Solution {
//This can also be done according to the practice of ordinary binary tree
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == p || root == q || root == null) return root;

TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);

if(left != null && right != null) return root;

if(left != null && right == null) return left;
else if(left == null && right != null) return right;
else return null;
}
}
```

However, because it is a binary search tree BST, we can also have another solution, which is to use the characteristic that the left tree is smaller than the root node and the right tree is larger than the root node. When the values of p and q nodes are less than the value of the current root node, we will traverse the left tree to find the nearest public node, otherwise, we can search to the right. If the values of p and q nodes are greater than the value of the current node, it means that they are the nearest public node and directly return the result. The recursive method is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/

class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//Directly return the result of recursive function
return fun(root,p,q);
}
//Recursive function
public TreeNode fun(TreeNode root,TreeNode p,TreeNode q){
//If you enter, it will be judged as empty. If root is empty, it will directly return null
if(root == null) return null;
//Because the binary search tree is ordered, we can carry out unilateral recursion according to this feature
//If the current node value is greater than the values of p and q, we will recurse to the left
if(root.val > p.val && root.val > q.val){
TreeNode left = fun(root.left,p,q);
//If left is not empty, you can return the answer directly
if(left != null) return left;
}
//If the current node value is less than the values of p and q, we will recurse to the right
if(root.val < p.val && root.val < q.val){
TreeNode right = fun(root.right,p,q);
//If right is not empty, we can return the answer directly if we find it
if(right != null) return right;
}
//If neither of the above conditions is satisfied
//This indicates that the value of the pq node and the value of the current node root are larger or smaller
//In this case, pq one is in the left subtree and the other is in the right subtree
//Then the current node must be the nearest public ancestor
return root;
}
}
```

The iterative method is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/

class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//Because the topic says that pq nodes must exist, so there must be public ancestors recently
//Therefore, we do not need to judge whether the left and right nodes are empty
//Because we can find the answer before we meet the empty node
while(true){
//The values of p and q are less than the value of the current node root
if(root.val > p.val && root.val > q.val){
//So let's iterate to the left
root = root.left;
}else if(root.val < p.val && root.val < q.val){
root = root.right;
}else {//If there is only one large and one small case left, the current node is the nearest common ancestor
//Terminate cycle
break;
}
}
//Returns the current node as the answer
return root;
}
}
```

# 701. Insert operation in binary search tree

Title Description:

Train of thought analysis:
We can redraw (construct) the binary tree, and then insert the value we want to insert when we encounter an empty node (hanging at the end is the most convenient method). It will be easier to understand the specific code.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode() {}
*     TreeNode(int val) { this.val = val; }
*     TreeNode(int val, TreeNode left, TreeNode right) {
*         this.val = val;
*         this.left = left;
*         this.right = right;
*     }
* }
*/
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
//According to the characteristics of binary search tree
//It's kind of like reconstructing this binary tree once
//If a null value is encountered during construction, the upward return will be inserted into the
//Hanging in the newly reconstructed binary tree
if(root == null){
TreeNode node = new TreeNode(val);
return node;
}
//If the current node value is greater than the inserted value, recurse to the left
if(root.val > val) root.left = insertIntoBST(root.left,val);
//If the current node value is less than the inserted value, recurse to the right
if(root.val < val) root.right = insertIntoBST(root.right,val);
//Returns the current node
return root;
}
}
```

# 450. Delete nodes in binary search tree

Title Description:

Train of thought analysis:
Boss Carl said it in detail. Just look at it. The comments in my code are also very clear.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode() {}
*     TreeNode(int val) { this.val = val; }
*     TreeNode(int val, TreeNode left, TreeNode right) {
*         this.val = val;
*         this.left = left;
*         this.right = right;
*     }
* }
*/
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//Air judgment
if(root == null) return null;
//If the value of the current node is equal to the value of the node to be deleted
if(root.val == key){
//If the left subtree of the current node is empty, we return the right subtree to the upper layer
//In this way, when the upper function reconstructs the binary tree, it will directly hang a tree
if(root.left == null) return root.right;
//If the right subtree of the current node is empty, we return the left subtree to the upper layer
else if(root.right == null) return root.left;
//Otherwise, the left and right subtrees are not empty
else{
//Record the right subtree of the current node with cur pointer
TreeNode cur = root.right;
//Loop through the leftmost leaf node of the right subtree of the current node
//Because you have to hang a subtree up when you go back
while(cur.left != null){
cur = cur.left;
}
//Then we hang the left tree of the current node to the right tree of the current node
//At the bottom of the left (combined with the moving picture of boss Carl)
cur.left = root.left;
//Finally, let the current node point to its right tree
root = root.right;
//Return the current node, and then the upper function will hang it in the
//We are on the regenerated tree
return root;
}
}
//The following is the case of not equal to, so you can continue recursive processing
//If the value of the current node is greater than the target deletion value, the left recursive deletion is performed
if(root.val > key) root.left = deleteNode(root.left,key);
//If the value of the current node is less than the target deletion value, right recursive deletion is performed
if(root.val < key) root.right = deleteNode(root.right,key);

//Return the current node, and the upper function is also used to hang on the tree
//The last returned node is the root node of the new tree we reconstructed
return root;
}
}
```

# 669. Pruning binary search tree

Title Description:

Train of thought analysis:
You can understand it by reading the code.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode() {}
*     TreeNode(int val) { this.val = val; }
*     TreeNode(int val, TreeNode left, TreeNode right) {
*         this.val = val;
*         this.left = left;
*         this.right = right;
*     }
* }
*/
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
//Air judgment
if(root == null) return null;

//The following two IFS are equivalent to deleting nodes that do not meet the requirements
//If the value of the current node is less than low, it will recursively search the right tree with large value
if(root.val < low){
//Because there may be qualified values in the right subtree of the current node, we have to get them in
return trimBST(root.right,low,high);
}
//If the value of the current node is greater than high, the left tree with smaller value will be searched recursively
if(root.val > high){
//Because the left subtree of the current node may have values that meet the conditions, we have to get them in
return trimBST(root.left,low,high);
}
//Processing normal nodes
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
//Return the current node to the previous function call and hang it on the new tree
return root;
}
}
```

# 108. Convert an ordered array into a binary search tree

Title Description:

Train of thought analysis:
You can understand it by reading the code. In fact, it is very similar to the previous topic and the implementation method is very similar.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode() {}
*     TreeNode(int val) { this.val = val; }
*     TreeNode(int val, TreeNode left, TreeNode right) {
*         this.val = val;
*         this.left = left;
*         this.right = right;
*     }
* }
*/
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
//Do it recursively according to the rules of middle order traversal
return fun(nums,0,nums.length-1);//Generally, the array length is - 1, and the same is true for bisection
}
//Recursive function
public TreeNode fun(int[] nums,int left,int right){
//If the array has no value, terminate and return null directly
if(left > right) return null;
//Take the intermediate value
//The following mid writing method can avoid array out of bounds
int mid = left + ((right - left) / 2);
//Create root node
TreeNode root = new TreeNode(nums[mid]);
//Then recurse to the left
root.left = fun(nums,left,mid-1);
//Recursion to the right
root.right = fun(nums,mid+1,right);
//Return the created node to the upper function for mounting
return root;
}
}
```

# 538. Convert binary search tree into cumulative tree

Title Description:

Train of thought analysis:
The meaning of the question is a little confused to tell the truth. In fact, it can be understood from another point of view. It is to get the order after the middle order traversal, and then accumulate the node value in reverse and assign it to the original node.
The idea is summarized as follows: traverse the BST in reverse middle order, then accumulate the values of each node with a global variable, and then re assign the value to the node.

The code is as follows:

```/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode() {}
*     TreeNode(int val) { this.val = val; }
*     TreeNode(int val, TreeNode left, TreeNode right) {
*         this.val = val;
*         this.left = left;
*         this.right = right;
*     }
* }
*/
class Solution {
//To tell you the truth, I'm a little confused
//It is to get the order after the middle order traversal, and then accumulate the node value in reverse and assign it to the original node
//Idea: traverse the BST in reverse order, and then use a global variable to accumulate the values of each node, and then assign a new value to the node
int sum;
public TreeNode convertBST(TreeNode root) {
//The reverse middle order is traversed in the order of right, middle and left
//Initialize sum
sum = 0;
//Call recursive function
fun(root);
//Returns the root of the tree
return root;
}
//Recursive function
public void fun(TreeNode root){
//If it is blank, because there is no return value, the function can be terminated directly if it is blank
if(root == null) return;

//Right recursion
fun(root.right);