递归函数中,如果不为void的话,在递归的时候需要return左边和右边返回的值
题目十四:最大二叉树
1. 构造二叉树用前序遍历:根左右;左右节点是否有if取决于递归终止条件是否有
2.思路
- 返回是Treenode构造完二叉树的根节点,传入的是数组
- 递归终止条件:传入的数组的大小==1也就是到叶子节点了
- 递归逻辑:
- 存最大值所在的下标index,最大值value,找到最大值;
- node.left:index>0保证数组元素个数>=1;左闭右开数组(0,index)也就是从第0个到index之前1个
- node.rightt:index<nums.size-1保证元素个数>=1;左闭右开数组(index+1,nums.size)
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructMaximumBinaryTree1(nums, 0, nums.length);
}
public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
if (rightIndex - leftIndex < 1) {// 没有元素了
return null;
}
if (rightIndex - leftIndex == 1) {// 只有一个元素
return new TreeNode(nums[leftIndex]);
}
int maxIndex = leftIndex;// 最大值所在位置
int maxVal = nums[maxIndex];// 最大值
for (int i = leftIndex + 1; i < rightIndex; i++) {
if (nums[i] > maxVal){
maxVal = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(maxVal);
// 根据maxIndex划分左右子树
root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
return root;
}
题目十五:合并二叉树
1. 617. 合并二叉树 - 力扣(LeetCode) :将两个二叉树对应位置的值进行相加合并
2. 思路(更改tree1的结构)
- 递归方法返回合并完的Treenode,参数是Treenode节点一和Treenode节点二
- 终止条件:如果tree1是null返回tree2,如果tree2是null返回tree1
- 递归逻辑:返回对应的根节点的子树给上一层,
- 中:tree1.val+=tree2.val
- 左:tree1.left=merge(tree1.left,tree2.left)
- 右:tree1.right=merge(tree1.right,tree2.right)
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1==null)return root2;
if(root2==null)return root1;
root1.val+=root2.val;
root1.left=mergeTrees(root1.left,root2.left);
root1.right=mergeTrees(root1.right,root2.right);
return root1;
}
题目十六:二叉搜索树中的搜索
1. 思路:要用result接住下面递归返回的节点
public TreeNode searchBST(TreeNode root, int val) {
if(root==null || root.val==val)return root;
TreeNode result=new TreeNode();
if(root.val>val)result= searchBST(root.left,val);
if(root.val<val)result= searchBST(root.right,val);
return result;
}
题目十七:验证二叉搜索树
1. 题目:98. 验证二叉搜索树 - 力扣(LeetCode)
2. 思路:如果没有节点也是二叉搜索树,要判断根节点比左子树大,不是单比root.left左孩子
TreeNode pre;
声明了一个变量但没有初始化,它默认值为null
。设置为全局变量才不会在每次递归的时候被初始化TreeNode pre = new TreeNode();
声明了一个变量并立即初始化,它指向了一个新创建的TreeNode
对象
class Solution {
TreeNode pre;//全局变量不会在每次递归的时候被初始化
public boolean isValidBST(TreeNode root) {
if(root==null)return true;
boolean result1=isValidBST(root.left);//左
//TreeNode pre=new TreeNode();不正确
if(pre!=null && pre.val>=root.val)return false;
pre=root;
boolean result2=isValidBST(root.right);//右
return result1&&result2;
}
}
题目十八:二叉搜索树的最小绝对差
1. 题目:530. 二叉搜索树的最小绝对差 - 力扣(LeetCode) :返回 树中任意两不同节点值之间的最小差值
2. 思路
(1)要设置全局变量pre和ans,来存储上一个节点和两个节点的差值最小值
(2)递归的时候重新写递归函数,因为最后返回最大值就行,所以void
class Solution {
TreeNode pre;
int ans=Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root==null)return 0;
huisu(root);
return ans;
}
public void huisu(TreeNode cur){
if(cur==null)return;
huisu(cur.left);
if(pre!=null){
ans=Math.min(ans,cur.val-pre.val);
}
pre=cur;
huisu(cur.right);
}
}
题目十九:二叉搜索树中的众树
1. 题目:. - 力扣(LeetCode)这里的二叉搜索树可以有很多个众数
2. 思路:二叉搜索树一定是中序遍历
(1)count是统计单个元素出现的频率;maxcount是当前遍历过的最高频率
(2)定义全局变量:pre指针,count,maxcount,int[] res放结果
(3)递归
- 参数是Treenode cur,返回值是void
- 终止条件:如果if(cur==null)return null
- 单层递归逻辑:用中序遍历,左中右
- 左:huisu(cur.left)
- 中:如果pre是null,第一个元素,count=1;如果pre和cur相等,count++;如果不相等count=1;统计(如果count==max就把当前的元素放入结果集)
- 右:huisu(cur.right)
class Solution {
List<Integer> ans=new ArrayList<>();
int count;
int maxcount;
TreeNode pre=null;
public int[] findMode(TreeNode root) {
huisu(root);
int[] res=new int[ans.size()];
for(int i=0;i< ans.size();i++){
res[i]=ans.get(i);
}
return res;
}
public void huisu(TreeNode cur){
if (cur==null)return;
huisu(cur.left);
if(pre==null )count=1;
else if(pre.val!= cur.val)count=1;
else if(pre.val==cur.val)count++;
pre=cur;
//处理maxcount
if(count==maxcount)ans.add(cur.val);
else if(count>maxcount){
maxcount=count;
ans.clear();
ans.add(cur.val);
}
huisu(cur.right);
return;
}
}
题目二十:求二叉树的最近公共祖先
1. . - 力扣(LeetCode) :自底向上处理结果,
- 第一种情况:左右子树只要出现了p或q就往上返回,在根节点进行判断
- 第二种情况:左孩子和根节点分别是p和q
2. 递归
- 返回值是Treenode,参数是root,p,q
- 边界条件:如果root为空,则返回空;如果root.va==pl或者root.val==q,则返回root
- 递归逻辑:后序,中要根据左和右来判断
- 左:Treenode left=huisu(root.left,q,p),left表示左子树有没有出现过p或者q
- 右:Treenode right=huisu(root.right,q,p),left表示右子树有没有出现过p或者q
- 中:如果left或者right不为空,则root就是最近公共祖先,则返回root
- 左不为空、右为空返回左;左为空、右不为空返回右;左右都为空则返回null
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if (root==null)return null;
if (root==p ||root==q)return root;
TreeNode left=lowestCommonAncestor(root.left,p,q);//左
TreeNode right=lowestCommonAncestor(root.right,p,q);//右
if (left==p && right==q)return root;//中
else if(left==q && right==p)return root;
else if (left==null && right!=null)return right;
else if(left!=null && right==null)return left;
else return null;//没有找到
}
题目二十一:二叉搜索树的最近公共祖先
1. 题目:代码随想录 (programmercarl.com)
2. 思路:如果从上往下遍历的时候,发现一个root的值在p和q中间,则root一定是最近的公共祖先,没有可能是次近的公共祖先,需要用return接住返回的点
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root.val>p.val && root.val>q.val)return lowestCommonAncestor(root.left,p,q);
if(root.val<p.val && root.val<q.val)return lowestCommonAncestor(root.right,p,q);
return root;
}
题目二十二:二叉搜索树中的插入操作
1. 题目:701. 二叉搜索树中的插入操作 - 力扣(LeetCode)
2. 思路:如果遍历到根节点,new一个新的节点并返回;遍历左子树和右子树的时候,用root.left和root.right接住return的点,return的是新的左子树或右子树
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root==null){
TreeNode newnode=new TreeNode(val);
return newnode;
};
if(root.val<val)root.right= insertIntoBST(root.right,val);
else if(root.val>val)root.left= insertIntoBST(root.left,val);
return root;
}
题目二十三:删除二叉搜索树中的节点
1. 题目: 450. 删除二叉搜索树中的节点 - 力扣(LeetCode)
2. 递归:不用去遍历整个二叉树,找到删除的点就终止
- (1) 返回值是Treenode,参数是root和key
- (2)边界条件:共五种情况
- 没有找到要删除的节点:if(root==null)返回空的,没有找到要删除的点
- 删的是叶子节点,左右不为空:如果左子树和右子树都为空,直接删除return null
- 删的节点左不为空、右为空:return root.left
- 删的节点左为空、右不为空:return root.right
- 删的节点左右都不为空:右孩子继位,原先的左子树放在右孩子的左子树的最下面。首先用cur指向右孩子,然后用while循环找到左子树的最左叶子节点。cur.left=root.left。再return root.right
- (3)递归逻辑
- if(val<root.val) root.left=huisu(root.left,key)用root.left接住新的节点
- if(val>root.val) root.right=huisu(root.right,key)用root.right接住新的节点
- 最后返回root
public TreeNode deleteNode(TreeNode root, int key) {
//边界条件
if(root==null)return null;//1.不存在
if(root.val==key){
//2.是叶子节点
if (root.left==null && root.right==null)return null;
//3.左不为空、右为空
else if (root.left!=null && root.right==null)return root.left;
//4.右不为空,左为空
else if (root.left==null && root.right!=null)return root.right;
//5.左右都不为空
else{//找到最左叶子节点
TreeNode cur=root.right;
while (cur.left!=null)cur=cur.left;
cur.left=root.left;
return root.right;
}
}
//递归逻辑
if(root.val<key)root.right=deleteNode(root.right,key);
if(root.val>key)root.left=deleteNode(root.left,key);
return root;
}
题目二十四:修剪二叉搜索树
2. 递归思路:根左右
- 返回值是Treenode,参数是边界值low、high
- 终止条件:if(root==null) return null
- 递归思路: if(root.val<low)huisu(root.right,left,right)去修建root的右子树,将修剪好树的新的根节点返回
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root==null)return null;//边界条件
if (root.val<low)return trimBST(root.right,low,high);//1.处理根
if (root.val>high)return trimBST(root.left,low,high);
root.left=trimBST(root.left,low,high);//2.左
root.right=trimBST(root.right,low,high);//3.右
return root;
}
题目二十五:将有序数组转化为二叉搜索树
1. 题目:108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode)
2. 思路:找到中间的点作为根节点,当数组长度是偶数的时候取左节点右节点都可以
- 返回值是Treenode也就是构造好的二叉搜索树,参数是int数组,left,right(左闭右闭)
- 终止条件:if(left>right)return null,当left=right的时候是只有一个元素是合法区间
- 单层递归:mid=(left+right)/2取下,构造二叉树
public TreeNode sortedArrayToBST(int[] nums) {
if(nums.length==0)return null;
return huisu(nums,0,nums.length-1);
}
public TreeNode huisu(int[] nums,int left,int right){//左闭右闭
if(left>right)return null;//边界条件
int mid=(left+right)/2;//中
TreeNode root=new TreeNode(nums[mid]);
root.left=huisu(nums,left,mid-1);//左
root.right=huisu(nums,mid+1,right);//右
return root;
}
题目二十六:把二叉搜索树转化为累加树
1. 题目:538. 把二叉搜索树转换为累加树 - 力扣(LeetCode) 前一个结点的更新值和本节点相加
2. 从后往前倒序相加:右中左,定义pre是前一个结点的数值,初始化为0
- 返回值是void,参数是Treenode cur
- 终止条件:if(cur==null)return;
- 递归逻辑:
- 右:huisu(cur.right)
- 中:cur.val+=pre;pre=cur.val
- 左:huisu(cur.left)
class Solution {
int pre=0;
public TreeNode convertBST(TreeNode root) {
huisu(root);
return root;
}
public void huisu(TreeNode cur){
if(cur==null)return;
huisu(cur.right);
cur.val+=pre;
pre=cur.val;
huisu(cur.left);
}
}