目录
一、力扣654.最大二叉树
1.1 题目
1.2 思路
做了从中序与后序遍历序列构造二叉树后,本题简单多了,思路相同轻松拿下!
1.3 代码
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums.length == 0){
return null;
}
return findNode(nums,0,nums.length-1);
}
//递归,区间遵循左闭右闭
public TreeNode findNode(int[] nums,int begin,int end){
//确定递归终止条件
if(begin > end){
return null;
}
//寻找最大值以及最大值的下标
int max = nums[begin];
int maxIndex = begin;
for(int i = begin;i<=end;i++){
if(nums[i] > max){
max = nums[i];
maxIndex = i;
}
}
TreeNode root = new TreeNode(max);
root.left = findNode(nums,begin,maxIndex-1);
root.right = findNode(nums,maxIndex+1,end);
return root;
}
}
二、力扣617.合并二叉树
2.1 题目
2.2 思路
同时前序遍历递归
2.3 代码
如果不改变原来两颗树的结构:
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
//同时前序遍历
if(root1 == null && root2 == null){
return null;
}
return preorder(root1,root2);
}
//同时前序遍历递归
public TreeNode preorder(TreeNode root1,TreeNode root2){
//递归终止条件
if(root1 == null && root2 == null){
return null;
}else if(root1!=null && root2 == null){
return root1;
}else if(root1==null && root2 != null){
return root2;
}
//中
TreeNode newRoot = new TreeNode();
newRoot.val = root1.val + root2.val;
//左右
newRoot.left = preorder(root1.left,root2.left);
newRoot.right = preorder(root1.right,root2.right);
return newRoot;
}
}
直接改造tree1,使其成为合并后的二叉树:
class Solution {
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
//同时前序遍历
if(root1 == null && root2 == null){
return null;
}
return preorder(root1,root2);
}
//同时前序遍历递归
public TreeNode preorder(TreeNode root1,TreeNode root2){
//递归终止条件
if(root1 == null && root2 == null){
return null;
}else if(root1!=null && root2 == null){
return root1;
}else if(root1==null && root2 != null){
return root2;
}
//中,直接在原tree1的基础上改造为合并后的二叉树
root1.val += root2.val;
//左右
root1.left = preorder(root1.left,root2.left);
root1.right = preorder(root1.right,root2.right);
return root1;
}
}
2.4 总结
本题目有一个关键点就是递归的终止条件,当两个节点只要其中的一个为null,那么就要return。
三、力扣700.二叉搜索树中的搜索
3.1 题目
3.2 思路
抓住二叉搜索树的特点即可。
3.3 代码
递归写法
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
//前序遍历,递归
if(root == null){
return null;
}
return search(root,val);
}
//递归
public TreeNode search(TreeNode node,int val){
//确定递归终止条件,关键点
if(node == null){
return null;
}
//单层递归逻辑
if(val > node.val){
return search(node.right,val);
}
if(val < node.val){
return search(node.left,val);
}
return node;
}
}
迭代写法
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
//迭代法
if(root == null){
return null;
}
TreeNode cur = root;
while(cur!=null){
if(val == cur.val){
return cur;
}else if(val > cur.val){
cur = cur.right;
}else if(val < cur.val){
cur = cur.left;
}
}
return cur;
}
}
四、力扣98.验证二叉搜索树
4.1 题目
4.2 思路
自己的思路:中序遍历二叉搜索树,将每个节点的val收集到数组中,那么得到的数组是一个从小到大排列的数组;判断该数组是不是从小到大的排列的,即当前数是否小于后一个数(二叉搜索树中不包含重复值)。
双指针优化:不需要设置一个数组来收集遍历的值,直接在二叉搜索树中比较。
4.3 代码
自己的思路:看起来时间复杂度有点高
class Solution {
public boolean isValidBST(TreeNode root) {
if(root == null){
return true;
}
List<Integer> res = new ArrayList<>();
inorder(root,res);
for(int i =0;i< res.size()-1;i++){
if(res.get(i) >= res.get(i+1)){
return false;
}
}
return true;
}
//递归中序遍历
public void inorder(TreeNode root,List<Integer> res){
//确定终止条件
if(root == null){
return;
}
//左中右
inorder(root.left,res);
res.add(root.val);
inorder(root.right,res);
}
}
推荐双指针优化(理解的不深刻,还需加强)
class Solution {
public TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
//双指针法pre,root中序遍历,当前节点root的值大于pre的值则合法,否则不合法
//判断特殊情况
if(root == null){
return true;
}
//中序遍历,左中右
boolean leftResult = isValidBST(root.left);
if(pre != null && root.val <= pre.val){
return false;
}
pre = root;
boolean rightResult = isValidBST(root.right);
return leftResult && rightResult;
}
}
4.4 总结
利用二叉搜索树的特性:中序遍历出来的数是从小到大有序的!
注意二叉树的定义,并不是左孩子小于根节点,右孩子大于根节点,而是左子树的全部节点小于根节点,右子树的全部节点大于根节点。