654.最大二叉树
思路:递归,这道题和利用中序和后序数组构造树以及利用前序和中序数组构造树两道题类似,
终止条件:
当遍历数组的范围为0,直接返回null 或只有一个元素则返回这个元素
单层递归逻辑:
我们每次需要找到nums数组中的最大值,根据最大值节点划分左右子树,对左右子树传入通过最大值划分好的区间索引进行dfs
代码实现
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
//最大二叉树
return dfs(nums,0,nums.length);//左闭右开
}
public TreeNode dfs(int[] nums,int leftIndex,int rightIndex){
//终止条件
if(leftIndex==rightIndex){return null;}
if(rightIndex-leftIndex==1){return new TreeNode(nums[leftIndex]);}//只有一个元素
//单层递归逻辑,找到最大值
int maxIndex=leftIndex;//记录最大值索引
int maxValue=nums[maxIndex];//记录最大值
for(int i=maxIndex+1;i<rightIndex;i++){//改成i=leftIndex,或者i=maxIndex都是ok的
if(nums[i]>maxValue){
maxValue=nums[i];
maxIndex=i;
}
}
// 根据最大值节点划分左右子树
TreeNode root=new TreeNode(maxValue);
root.left=dfs(nums,leftIndex,maxIndex);
root.right=dfs(nums,maxIndex+1,rightIndex);
return root;
}
}
617.合并二叉树
思路:前序遍历+递归,
1.确定递归函数的参数和返回值:
首先要合入两个二叉树,那么参数至少是要传入两个二叉树的根节点,返回值就是合并之后二叉树的根节点。
2.递归终止条件
假设两个树遍历的节点t1 和 t2,如果t1 == NULL 了,两个树合并就应该是 t2 了(如果t2也为NULL也无所谓,合并之后就是NULL)。
反过来如果t2 == NULL,那么两个数合并就是t1(如果t1也为NULL也无所谓,合并之后就是NULL)。
3.递归单层逻辑
这里重复利用一下t1这个树,t1就是合并之后树的根节点(就是修改了原来树的结构)。
代码实现
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
return dfs(root1,root2);
}
public TreeNode dfs(TreeNode root1, TreeNode root2){
//终止条件
if(root1==null){return root2;}
if(root2==null){return root1;}
//以root1为主树
root1.val+=root2.val;
root1.left=dfs(root1.left,root2.left);
root1.right=dfs(root1.right,root2.right);
return root1;
}
}
700.二叉搜索树中的搜索
思路1:递归法,二叉搜索树的节点是有序的,因此我们可以有方向的去搜索
1.确定递归函数的参数和返回值
2.确定递归终止条件
root为空或者找到这个数值了,就返回root节点
3.确定递归逻辑
二叉搜索树是有序的,那么我们就可以有方向的去搜索
class Solution {
public TreeNode searchBST(TreeNode root, int val) {//
return dfs(root,val);
}
public TreeNode dfs(TreeNode root, int val){
//如果root为空,或者找到这个数值了,就返回root节点。
if(root==null||root.val==val){
return root;
}
// 因为二叉搜索树的节点是有序的,所以可以有方向的去搜索。
TreeNode result=null;
if(root.val>val){
//往左边搜搜
result=dfs(root.left,val);
}
if(root.val<val){
//往右边搜搜
result=dfs(root.right,val);
}
return result;
}
}
思路2:迭代法
一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。
对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。
对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。
而对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。
例如要搜索元素为3的节点,我们不需要搜索其他节点,也不需要做回溯,查找的路径已经规划好了。
中间节点如果大于3就向左走,如果小于3就向右走.
代码实现:这道题的迭代法不需要借助栈或者队列作为辅助,只需要利用二叉搜索树的有序性进行遍历
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
while(root!=null){
if(root.val>val){
//往左走
root=root.left;
}
else if(root.val<val){
root=root.right;
}
else{
return root;
}
}
return null;
}
}
所以针对二叉搜索树的题目,一样要利用其特性。
98.验证二叉搜索树
验证二叉搜索树是否合规的,可以对二叉搜索树进行中序遍历,得到的应该会是一个递增数组,我们每次记录前一个节点,将前一个节点的值和当前遍历的节点进行比较
class Solution {
TreeNode pre=null;//记录前一个节点
public boolean isValidBST(TreeNode root) {
// 对二叉搜索树如果进行中序遍历,那么得到的就会是一个递增数组,
if(root==null){return true;}//终止条件
//单层递归逻辑,中序遍历
boolean left=isValidBST(root.left);
if(pre!=null&&pre.val>=root.val){return false;}//因为我们想要的是递增的,所以如果前一个节点的值大于当前root节点的值,那么不符合,需要return false
pre=root;//记录前一个节点
boolean right=isValidBST(root.right);
return left&&right;
}
}