今天主要学习了二叉搜索树的相关题目,学习到怎么同时递归操作两棵树。
1.力扣654(最大二叉树)
首先我们要知道最大二叉树是什么,下面是最大二叉树的定义:
- 二叉树的根是数组中的最大元素。
- 左子树是通过数组中最大值左边部分构造出的最大二叉树。
- 右子树是通过数组中最大值右边部分构造出的最大二叉树。
本题方便理解,我们利用前序遍历来构建二叉树,我们首先创建中节点,然后创建左节点和右节点,接下来用递归三部曲来创建:
- 确定递归函数的参数和返回值:参数就是传入的是存放元素的数组和左右边界,返回该数组构造的二叉树的头结点。
public TreeNode constructTree(int[] nums,int leftIndex,int rightIndex)
- 确定终止条件:当区间元素就剩一个的时候,我们直接返回并创建节点,若左右边界混乱时,我们也返回
if (rightIndex - leftIndex < 1) {// 没有元素了
return null;
}
if(rightIndex-leftIndex==1){
return new TreeNode(nums[leftIndex]);
}
- 确定单层递归的逻辑:首先我们先遍历出数组中的最大值,然后我们进行创建节点,随后我们创建中节点,然后我们递归创建左区间和右区间
//中
int maxValue = nums[leftIndex];
int maxIndex = leftIndex;
for(int i=leftIndex;i<rightIndex;i++){
if(nums[i]>maxValue){
maxValue=nums[i];
maxIndex = i;
}
}
TreeNode node = new TreeNode(maxValue);
//左
node.left = constructTree(nums,leftIndex,maxIndex);
//右
node.right = constructTree(nums,maxIndex+1,rightIndex);
return node;
下面是整体代码:
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums.length==1){
return new TreeNode(nums[0]);
}
return constructTree(nums,0,nums.length);
}
public TreeNode constructTree(int[] nums,int leftIndex,int rightIndex) {
if (rightIndex - leftIndex < 1) {// 没有元素了
return null;
}
if(rightIndex-leftIndex==1){
return new TreeNode(nums[leftIndex]);
}
//中
int maxValue = nums[leftIndex];
int maxIndex = leftIndex;
for(int i=leftIndex;i<rightIndex;i++){
if(nums[i]>maxValue){
maxValue=nums[i];
maxIndex = i;
}
}
TreeNode node = new TreeNode(maxValue);
//左
node.left = constructTree(nums,leftIndex,maxIndex);
//右
node.right = constructTree(nums,maxIndex+1,rightIndex);
return node;
}
2.力扣617(合并二叉树)
合并二叉树这个题目的重点是递归操作两个二叉树,若相同位置处的某个节点为空就直接返回不为空的那个节点,若都存在的话就相加后并返回,最终返回根节点。下面利用递归三部曲来构建二叉树:
- 确定递归函数的参数和返回值:首先那么要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。
public TreeNode mergeTree(TreeNode root1, TreeNode root2)
- 确定终止条件:因为是传入了两个树,那么就有两个树遍历的节点,此时会有三种情况发生:若其中一个为空,就返回另一个,若都不为空就相加后返回。
if(root1==null){
return root2;
}
if(root2==null){
return root1;
}
- 确定单层递归的逻辑:这里我们直接进行相加操作就可以了
root1.val+=root2.val;
root1.left= mergeTree(root1.left,root2.left);
root1.right=mergeTree(root1.right,root2.right);
return root1;
整体代码如下:
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return mergeTree(root1,root2);
}
public TreeNode mergeTree(TreeNode root1, TreeNode root2) {
if(root1==null){
return root2;
}
if(root2==null){
return root1;
}
root1.val+=root2.val;
root1.left= mergeTree(root1.left,root2.left);
root1.right=mergeTree(root1.right,root2.right);
return root1;
}
3.力扣700(二叉搜索树中搜索)
在本题中我们要充分利用二叉搜索树中的这个结构,即节点的左子树都小于中节点,右节点都大于中节点,本体利用递归三部曲来解决:
- 确定递归函数的参数和返回值:递归函数的参数传入的就是根节点和要搜索的数值,返回的就是以这个搜索数值所在的节点。
public TreeNode search(TreeNode root, int val)
- 确定终止条件:如果root为空,或者找到这个数值了,就返回root节点。
if(root==null||root.val==val){
return root;
}
- 确定单层递归的逻辑:若节点值大于目标值就去左子树找,否则就去右子树找
TreeNode res = null;
if(val<root.val){
res = search(root.left,val);
}
if(val>root.val){
res = search(root.right,val);
}
return res;
整体代码:
public TreeNode searchBST(TreeNode root, int val) {
return search(root,val);
}
public TreeNode search(TreeNode root, int val) {
if(root==null||root.val==val){
return root;
}
TreeNode res = null;
if(val<root.val){
res = search(root.left,val);
}
if(val>root.val){
res = search(root.right,val);
}
return res;
}
4.力扣98(验证二叉树)
本题要来验证二叉搜索树,容易犯的错误就是只比较中节点大于左右孩子节点,我们应该比较的是中节点和整个左子树的大小和右子树的大小,其次解决本题最重要的一点就是二叉搜索树在中序遍历的时候,会保持单调递增的顺序,所以我们可以定义一个节点指向前一个结点,以此向下遍历。下面利用递归三部曲来解决:
- 确定递归函数返回值以及参数:我们在定义了一个全局节点,用来记录上一个接单。
public boolean isBST(TreeNode root)
- 确定终止条件:若节点为空就返回
if(root==null){
return true;
}
- 确定单层递归的逻辑:首先判断左节点,然后判断前一个结点是否满足小于后一个节点,若不满足就返回false,然后递归判断右节点。
//左
boolean left = isBST(root.left);
if(pre!=null&&pre.val>=root.val){
return false;
}
pre =root;
//右
boolean right = isBST(root.right);
return left&right;
整体代码:
TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
return isBST(root);
}
public boolean isBST(TreeNode root) {
if(root==null){
return true;
}
//左
boolean left = isBST(root.left);
if(pre!=null&&pre.val>=root.val){
return false;
}
pre =root;
//右
boolean right = isBST(root.right);
return left&right;
}