一、二叉搜索树的最近公共祖先(利用二叉搜索树的性质)
思路:如果pq节点的val都比node小的话,那么他们的最近公共祖先一定在node的左子树中;
如果都大的话,那么一定在node的右子树中
如果一大一小的话,那么该节点就一定是最近公共祖先
代码:
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root==null)return null;
//如果节点的值比pq的值都大
if(root.val>p.val&&root.val>q.val){
TreeNode result=lowestCommonAncestor(root.left,p,q);
if(result!=null)return result;
}
//如果节点的值比pq的值都小
if(root.val<p.val&&root.val<q.val){
TreeNode result=lowestCommonAncestor(root.right,p,q);
if(result!=null)return result;
}
//如果节点的值比一个大 一个小
return root;
}
二、二叉搜索树中的插入操作(往叶子节点上插入即可)
迭代法:
首先通过一个while循环,找到适合的叶子节点,然后插入val值的TreeNode节点即可。
这里用一个TreeNode pre来表示上一次遍历到的节点,当while条件不符合的时候,root就会为空,此时pre刚好是最后一个叶子节点。然后根据val值,插入到左边还是右边
代码:
public TreeNode insertIntoBST(TreeNode root, int val) {
//如果根节点都为空的话 那么直接创建一个节点
if(root==null)return new TreeNode(val);
TreeNode newNode=new TreeNode(val);
TreeNode newRoot=root;
TreeNode pre=root;
while(root!=null){
pre=root;
if(root.val>val)root=root.left;
else if(root.val<val)root=root.right;
}
if(pre.val>val)pre.left=newNode;
if(pre.val<val)pre.right=newNode;
return newRoot;
}
递归法:
public TreeNode insertIntoBST(TreeNode root, int val) {
//如果根节点都为空的话 那么直接创建一个节点
return traversal(root,val);
}
public TreeNode traversal(TreeNode root,int val){
if(root==null)return new TreeNode(val);
if(root.val>val){
root.left=traversal(root.left,val);
}
else if(root.val<val){
root.right=traversal(root.right,val);
}
return root;
}
递归找到要添加到子节点的位置,如果==null,说明找到了。然后root.left或者right=traversal(root.xxx,val);
三、删除二叉搜索树中的节点
删除二叉搜索树中的节点会遇到五种情况:
1.找不到val=key的节点 node==null 直接返回node
2.存在key的节点,为叶子节点,直接return null
3.左不空右空,return node.left
4.左空右不空 return node.right
5.左右都不空(比较麻烦)
这里选择将右子树放到root.left下面,然后将左子树挂到右子树最左的节点下面。
TreeNode cur=root.right.
while(cur.left!=null)cur=cur.left;
cur.left=root.left;
return root.right
代码:
public TreeNode deleteNode(TreeNode root, int key) {
return traversal(root, key);
}
public TreeNode traversal(TreeNode root, int key) {
// 1.没找到 2.叶子节点 3.左不空右空 4.左空右不空 5.左右都不空
// 先写终止条件 再写单层递归逻辑
if (root == null)
return root;// 没找到
if (key == root.val) {
if(root.right==null)return root.left;
else if(root.left==null)return root.right;
else {
// 左右都不为空 因为被删掉节点的左子树要挂在右子树的最左节点上
TreeNode cur = root.right;
while (cur.left != null) {
cur = cur.left;
}
cur.left = root.left;
return root.right;
}
}
if (root.val > key)
root.left = traversal(root.left, key);
if (root.val < key)
root.right = traversal(root.right, key);
return root;
}
四、修建二叉搜索树
给你二叉搜索树的根节点 root
,同时给定最小边界low
和最大边界 high
。通过修剪二叉搜索树,使得所有节点的值在[low, high]
中。修剪树 不应该 改变保留在树中的元素的相对结构 ,返回修改后的根节点
1.返回值:TreeNode root 参数TreeNode root,int low,int high
2.终止条件:if(root==null)return root
3.递归逻辑:
如果节点的值在low和high之间,直接递归左子树和右子树
如果val<low,遍历右子树,因为左子树一定是小于low的。
如果val>high,遍历左子树,因为右子树一定是大于high的
public TreeNode trimBST(TreeNode root, int low, int high) {
return traversal(root,low,high);
}
public TreeNode traversal(TreeNode root,int low,int high){
//写终止条件
if(root==null)return root;
//如果根节点是小于val的,那么左子树一定小于val 只需要递归遍历右子树就行
if(root.val<low){
return traversal(root.right,low,high);
}
//如果根节点是大于val的,那么右子树一定大于val 只需要遍历递归左子树就行
if(root.val>high){
return traversal(root.left,low,high);
}
//如果根节点的val是low->high之间
root.left=traversal(root.left,low,high);
root.right=traversal(root.right,low,high);
return root;
}
五、将有序数组转换为二叉搜索树
给你一个整数数组 nums
,其中元素已经按 升序 排列,请你将其转换为一棵
平衡二叉搜索树。
思路:因为是平衡二叉搜索树,所以两边的节点应该是相同的。又因为是升序排列,每次找到中间下标作为根节点就可以。然后再递归调用左子树和右子树。
注意:终止条件left<right和left<=right。如果是left<=right。代表着:left==right的时候,递归就会终止,我right是左闭右开的,传入right的时候为,nums.length。如果是left<right.说明left和right可以相等。
代码:
public TreeNode sortedArrayToBST(int[] nums) {
//中序遍历
return traversal(nums,0,nums.length);
}
public TreeNode traversal(int[] nums,int left,int right){
if(left>=right)return null;
int midIndex=(left+right)/2;
TreeNode node=new TreeNode(nums[midIndex]);
node.left=traversal(nums,left,midIndex);
node.right=traversal(nums,midIndex+1,right);
return node;
}
六、把二叉搜索树转换为累加树(双指针)
给定一个二叉搜索树,请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。
思路:使用双指针,递归右子树,然后每一个节点的val值等于root.val+pre.val。顺序为右中左,所以先递归右子树,然后root.val+=pre.val,pre=root。然后递归右子树
代码:
private TreeNode pre=new TreeNode(0);
public TreeNode convertBST(TreeNode root) {
//使用一个pre指向前一个指针
traversal(root);
return root;
}
public void traversal(TreeNode root){
if(root==null)return;
traversal(root.right);
root.val+=pre.val;
pre=root;
traversal(root.left);
}