public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() {}
TreeNode(int val) { this.val = val; }
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
如果一棵二叉树只有度为0的结点和度为2的结点,并且度为0的结点在同一层上,则这棵二叉树为满二叉树。深度为k,有2^k-1个节点的二叉树。
完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2^(h-1) 个节点。
有序树、左小右大
是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。
个人体会
二叉树的题目就是选择正确的遍历方式,再加上题目的要求,以及某些特殊二叉树的性质,去解题。
层序遍历
相关题目 推荐
102.二叉树的层序遍历
107.二叉树的层次遍历II
199.二叉树的右视图
637.二叉树的层平均值
429.N叉树的层序遍历
515.在每个树行中找最大值
116.填充每个节点的下一个右侧节点指针
117.填充每个节点的下一个右侧节点指针II
104.二叉树的最大深度
111.二叉树的最小深度
终止条件: null return
传递参数: root result
单层逻辑: 按一定顺序处理 遇到处理节点 add
中左右 经常有回溯的味道
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preorder(root,result);
return result;
}
public void preorder(TreeNode root,List<Integer> result){
if (root == null){return;}
result.add(root.val);
preorder(root.left,result);
preorder(root.right,result);
}
}
左右中
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer> ();
postorder(root,result);
return result;
}
public void postorder(TreeNode root,List<Integer> result){
if (root == null){return;}
postorder(root.left,result);
postorder(root.right,result);
result.add(root.val);
}
}
左中右
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer> ();
inorder(root,result);
return result;
}
public void inorder(TreeNode root,List<Integer> result){
if (root == null){return;}
inorder(root.left,result);
result.add(root.val);
inorder(root.right,result);
}
}
递归的实现就是:每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
因此可以利用栈实现二叉树的遍历。
总结
弄清楚入栈和出栈顺序,动画参考添加链接描述
前序和后序逻辑一致,后序需要再做一个反转操作。
中序遍历,访问和处理不一致(深刻理解这句话), 引入指针进行判断
若分析不清楚 可画图帮助分析
遍历顺序: 中左右
入栈: 中右左
出栈: 中左右
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<>();//创建一个栈
if (root == null){return result;}
stack.push(root);//把根节点入栈
while (!stack.isEmpty() ){//只要栈不为空
TreeNode temp = stack.pop();
result.add(temp.val);//取出栈的最后一个元素
if (temp.right != null){
stack.push(temp.right);//右
}
if (temp.left != null){
stack.push(temp.left);//左
}
}
return result;
}
}
遍历顺序: 左右中
在前序基础上左,入栈 中左右 ,出栈为 中右左,反转为 左右中
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
if (root == null){return result;}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode temp = stack.pop();
result.add(temp.val);
if (temp.left != null){
stack.push(temp.left);
}
if( temp.right != null){
stack.push(temp.right);
}
}
Collections.reverse(result);
return result;
}
}
遍历顺序:左中右
但是先处理的是中节点,先访问的是左节点,造成处理顺序和访问顺序是不一致的。
root就是中节点,想办法解决访问和处理不一致的问题,故引入指针cur,进行判断,只要左空了,那就处理中,再访问右
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer> ();
Stack<TreeNode> stack = new Stack<>();
if (root==null){return result;}
TreeNode cur = root;
//分别对左右子树是否为空进行判断
//先把左树放进栈里,若左空了就弹出,开始处理中之后,访问右
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);
cur = cur.left;//访问左
}
else{//左子树空了就把stack弹出
cur = stack.pop();
result.add(cur.val);//处理中
cur = cur.right;//访问右
}
}
return result;
}
}
前面的迭代法,写法风格不一致,为了解决该问题,提出以下方法
将访问的节点放入栈中,把要处理的节点也放入栈中但是要做标记。就是要处理的节点放入栈之后,紧接着放入一个空指针作为标记
取出栈的最后一个元素,遇到null,则先删除null,再删除最后一个元素,并将其值放入result,不是null,则根据遍历顺序放入null
//遍历顺序:左中右
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer> ();
Stack<TreeNode> stack = new Stack<>();
if (root!=null){
stack.push(root);}
while (!stack.isEmpty()){
TreeNode node = stack.peek();
if (node != null){
stack.pop();
if(node.right!=null){stack.push(node.right);}//右
stack.push(node);
stack.push(null);//未处理的加null标记
if(node.left != null) {stack.push(node.left);}//左
}
else{
stack.pop();//删除空白后处理
node = stack.peek();
stack.pop();
result.add(node.val);
}
}
return result;
}
}
需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑
两个while循环 一个对整个队列判断,另外一个判断每一层,以len记录每一层的元素个数,temp变量记录每一层的结果,入队顺序为左右
class Solution {
//迭代法
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
if (root == null){return result;}
Queue<TreeNode> que = new LinkedList<TreeNode>();
que.offer(root);
while( !que.isEmpty()){
List<Integer> temp = new ArrayList<Integer>();//每一层的变量
int len = que.size();//每一层的个数
//每一层的逻辑
while (len > 0){
TreeNode node = que.poll();
temp.add(node.val);
if(node.left != null){que.offer(node.left);}
if(node.right != null){que.offer(node.right);}
len--;
}
//每一层装完后加到result
result.add(temp);
}
return result;
}
}
单层逻辑: 记录深度,添加结果值
访问顺序:左右
class Solution {
List<List<Integer>> result = new ArrayList<List<Integer>>();
public List<List<Integer>> levelOrder(TreeNode root) {
dfsOrder(root,0);
return result;
}
public void dfsOrder(TreeNode root,Integer deep){
if (root == null){return;}//递归终止条件
//单层逻辑
deep++; //遍历一次 深度加一
if (result.size()<deep){
List<Integer> temp = new ArrayList<Integer>();
result.add(temp);
}//给结果加上层次
result.get(deep-1).add(root.val);
dfsOrder(root.left,deep);
dfsOrder(root.right,deep);
}
}
class Solution {
public boolean isSymmetric(TreeNode root) {
return compareHelp(root.left,root.right);
}
public boolean compareHelp(TreeNode leftNode,TreeNode rightNode){
if (leftNode == null && rightNode != null){return false;}
if (leftNode != null && rightNode == null){return false;}
if (leftNode == null && rightNode == null){return true;}
if (leftNode.val != rightNode.val){return false;}
boolean compareLeft = compareHelp(leftNode.left,rightNode.right);
boolean compareRight = compareHelp(leftNode.right,rightNode.left);
return compareLeft&&compareRight;
}
}
本题可以使用前序(中左右),也可以使用后序遍历(左右中),使用前序求的就是深度,使用后序求的是高度。
二叉树节点的深度:指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始)
二叉树节点的高度:指从该节点到叶子节点的最长简单路径边的条数后者节点数(取决于高度从0开始还是从1开始)
而根节点的高度就是二叉树的最大深度,所以本题中我们通过后序求的根节点高度来求的二叉树最大深度。
class Solution {//层序遍历
public int maxDepth(TreeNode root) {
if( root == null) {return 0;}
Queue<TreeNode> que = new LinkedList<TreeNode>();
que.offer(root);
int depth = 0;
while (!que.isEmpty()){
int length = que.size();
while (length>0){
TreeNode node = que.poll();
if(node.left != null) {que.offer(node.left);}
if (node.right != null) {que.offer(node.right);}
length--;
}
depth++;
}
return depth;
}
}
//前序遍历
//从上到下
class Solution {
int res;
public int maxDepth(TreeNode root) {
res = 0;
if(root == null ){return 0;}
getDepth(root,1);//深度从1开始
return res;
}
public void getDepth(TreeNode root,int depth){
res = Math.max(depth,res);//处理中节点
if(root.left==null&&root.right==null){
return; //终止条件
}
if(root.left!=null){
depth++;
getDepth(root.left,depth);
depth--;
}
if(root.right!=null){
depth++;
getDepth(root.right,depth);
depth--;
}
return;
}
}
/*
// Definition for a Node.
class Node {
public int val;
public List children;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, List _children) {
val = _val;
children = _children;
}
};
*/
//层序遍历 多少层即深度
class Solution {
public int maxDepth(Node root) {
if(root == null) {return 0;}
int depth = 0;//总共有多少层
Queue<Node> que = new LinkedList<>();
que.offer(root);
while(!que.isEmpty()){
int length = que.size();//每一层的大小
depth++;
while(length>0){
Node temp = que.poll();
for(int i = 0;i<temp.children.size();i++){
if(temp.children.get(i)!=null){
que.offer(temp.children.get(i));
}
}
length--;
}
}
return depth;
}
}
求二叉树的最小深度和求二叉树的最大深度的差别主要在于处理左右孩子不为空的逻辑。
class Solution {
public int minDepth(TreeNode root) {
if (root == null){return 0;}
int leftDepth = minDepth(root.left);
int rightDepth = minDepth(root.right);
if (root.left == null){return rightDepth+1;} //与最大深度不同之处
if (root.right == null) {return leftDepth+1;}
return Math.min(leftDepth,rightDepth)+1;
}
}
//对比最大深度
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {return 0;}
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth,rightDepth)+1;
}
}
class Solution {
public int countNodes(TreeNode root) {
if (root == null) {return 0;}
int leftNum = countNodes(root.left);
int rightNum = countNodes(root.right);
int num = leftNum + rightNum +1;
return num;
}
}
class Solution {
public int countNodes(TreeNode root) {
int num = 0;
if (root == null) {return num;}
Queue<TreeNode> que = new LinkedList<TreeNode>();
que.offer(root);
while( !que.isEmpty()){
int length = que.size();
while(length > 0){
TreeNode node = que.poll();
num++;
if(node.left != null){que.offer(node.left);}
if(node.right != null) {que.offer(node.right);}
length--;
}
}
return num;
}
}
class Solution {
public int countNodes(TreeNode root) {
if (root == null){return 0;}
int leftDepth = 0;
int rightDepth = 0;
TreeNode left = root.left;
TreeNode right = root.right;
while (left != null){
left = left.left;
leftDepth++;
}
while (right != null){
right = right.right;
rightDepth++;
}
//由于完全二叉树特点,左右深度一致必然为满二叉树
if (leftDepth == rightDepth){return (2<<leftDepth) - 1;}//终止条件
//不断地遍历必然会出现满二叉树
int leftNum = countNodes(root.left); //左
int rightNum = countNodes(root.right); //右
int res = leftNum + rightNum + 1; //中
return res;
}
}
class Solution {
public boolean isBalanced(TreeNode root) {
return getHight(root) != -1; //高度大于1返回-1
}
public int getHight(TreeNode root){//后序遍历
if (root == null) {return 0;}
int leftHigh = getHight(root.left);//左
if (leftHigh == -1){return -1;}//一个子树不符合,整体不符合
int rightHigh = getHight(root.right);//右
if (rightHigh == -1) {return -1;}
if (Math.abs(leftHigh-rightHigh)>1){return -1;}
return Math.max(leftHigh,rightHigh) + 1;
}
}
class Solution {
List<String> res = new ArrayList<String>();
public List<String> binaryTreePaths(TreeNode root) {
if (root == null){
return res;
}
List<Integer> path = new ArrayList<Integer>();
pathHelper(root,path);
return res;
}
public void pathHelper(TreeNode root,List<Integer> path){
//处理中节点
path.add(root.val);
if(root.left==null && root.right==null){//终止条件
StringBuilder sb = new StringBuilder();
for(int i = 0;i<path.size()-1;i++){
sb.append(path.get(i)).append("->");
}
sb.append(path.get(path.size()-1));
//如何构建字符串:先用一个list把val加进来,然后每个值中间插入->
res.add(sb.toString());
}
//左
if(root.left!=null){
pathHelper(root.left,path);
path.remove(path.size()-1);
}
//右
if(root.right!=null){
pathHelper(root.right,path);
path.remove(path.size()-1);
}
}
}
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) {return false;}
return pathHelper(root,targetSum);
}
public boolean pathHelper(TreeNode root,int count){
count = count - root.val;
if (root.left == null && root.right == null && count == 0){
return true;//终止条件
}
if (root.left != null){//左不为空
boolean left = pathHelper(root.left,count);
if(left) {return true;}//找到了
}
if (root.right != null){
boolean right = pathHelper(root.right,count);
if(right) {return true;}
}
return false;
}
}
class Solution {
int sum = 0;
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> res = new ArrayList<>();
if(root == null){return res;}
LinkedList<Integer> path = new LinkedList<>();
pathHelper(root,targetSum,res,path);
return res;
}
//前序遍历 中左右
public void pathHelper(TreeNode root,int targetSum,List<List<Integer>> res,LinkedList<Integer> path){
path.add(root.val);
sum += root.val;
if(root.left == null && root.right == null){//找到叶子节点
if(sum == targetSum){
res.add(new ArrayList<>(path));//和为目标值 就把结果加进去
}
return;
}
if(root.left != null){
pathHelper(root.left,targetSum,res,path);
int leftVal = path.removeLast();
sum -= leftVal;
}
if(root.right != null){
pathHelper(root.right,targetSum,res,path);
int rightVal = path.removeLast();
sum -= rightVal;
}
}
}
//后序遍历:返回和
class Solution {
int sum = 0;
public int sumOfLeftLeaves(TreeNode root) {
return sumHelper(root,0);
}
public int sumHelper(TreeNode root,int sum){
if(root==null){return 0;}
int leftSum = sumHelper(root.left,sum);//左
int rightSum = sumHelper(root.right,sum);//右
if(root.left!=null&&root.left.left==null&&root.left.right==null){//判断是否为左叶子
sum += root.left.val;
}
return leftSum+rightSum+sum;//处理中
}
}
class Solution {
public int findBottomLeftValue(TreeNode root) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
Queue<TreeNode> que = new LinkedList<TreeNode>();
que.offer(root);
while (!que.isEmpty()){
List<Integer> path = new ArrayList<Integer>();
int len = que.size();
while(len > 0){//每一层的遍历
TreeNode node = que.poll();
path.add(node.val);
if (node.left != null){ que.offer(node.left);}
if (node.right != null){ que.offer(node.right);}
len--;
}
result.add(path);
}
int value = result.get(result.size()-1).get(0);
return value;
}
}
//前序遍历
//当到达最大深度时,取第一个元素
class Solution {
int value = 0;
int Deep = -1;
public int findBottomLeftValue(TreeNode root) {
findHelper(root,0);
return value;
}
public void findHelper(TreeNode root,int deep){
if(root==null){return ;}
if(root.left == null && root.right==null){
if(deep>Deep){
value = root.val;
Deep = deep;
}
}
if(root.left != null){findHelper(root.left,deep+1);}
if(root.right != null){findHelper(root.right,deep+1);}
}
}
class Solution {
int res;
public int diameterOfBinaryTree(TreeNode root) {
dfs(root);
return res-1;
}
public int dfs(TreeNode node){
if(node == null) return 0;
int left = dfs(node.left);
int right = dfs(node.right);
res = Math.max(res,left+right+1);
return Math.max(left,right)+1;
}
}
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null ) {return null;}
swap(root);
invertTree(root.left);
invertTree(root.right);
return root;
}
public void swap(TreeNode node){
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
}
}
- 思路
找到后序数组最后一个元素在中序数组的位置,作为切割点
切割中序数组,切成中序左数组和中序右数组
切割中序数组,切成中序左数组和中序右数组
递归处理左区间和右区间
class Solution {
Map<Integer,Integer> map = new HashMap<>();
public TreeNode buildTree(int[] inorder, int[] postorder) {
for (int i = 0;i<inorder.length;i++){
map.put(inorder[i],i);//存放中序数组
}
//区间遵循左闭右闭准则
return buildHelp(inorder,0,inorder.length-1,postorder,0,postorder.length-1);
}
public TreeNode buildHelp(int[] inorder,int inBegin,int inEnd,int[] postorder,int postBeigin,int postEnd){
if (inBegin > inEnd || postBeigin > postEnd){return null;}//终止条件
//单层逻辑
int val = postorder[postEnd];//根节点的值
TreeNode root = new TreeNode(val);
int rootIndex = map.get(val);//根节点在中序数组的序号,
int lengthLeft = rootIndex - inBegin;//左子树的长度
root.left = buildHelp(inorder,inBegin,rootIndex-1,
postorder,postBeigin,postBeigin+lengthLeft-1);//处理左子树
root.right = buildHelp(inorder,rootIndex+1,inEnd,
postorder,postBeigin+lengthLeft,postEnd-1);
return root;
}
}
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
private Map<Integer, Integer> indexMap;
public TreeNode myBuildTree(int[] preorder, int[] inorder, int preorder_left, int preorder_right, int inorder_left, int inorder_right) {
if (preorder_left > preorder_right) {
return null;
}
// 前序遍历中的第一个节点就是根节点
int preorder_root = preorder_left;
// 在中序遍历中定位根节点
int inorder_root = indexMap.get(preorder[preorder_root]);
// 先把根节点建立出来
TreeNode root = new TreeNode(preorder[preorder_root]);
// 得到左子树中的节点数目
int size_left_subtree = inorder_root - inorder_left;
// 递归地构造左子树,并连接到根节点
// 先序遍历中「从 左边界+1 开始的 size_left_subtree」个元素就对应了中序遍历中「从 左边界 开始到 根节点定位-1」的元素
root.left = myBuildTree(preorder, inorder, preorder_left + 1, preorder_left + size_left_subtree, inorder_left, inorder_root - 1);
// 递归地构造右子树,并连接到根节点
// 先序遍历中「从 左边界+1+左子树节点数目 开始到 右边界」的元素就对应了中序遍历中「从 根节点定位+1 到 右边界」的元素
root.right = myBuildTree(preorder, inorder, preorder_left + size_left_subtree + 1, preorder_right, inorder_root + 1, inorder_right);
return root;
}
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n = preorder.length;
// 构造哈希映射,帮助我们快速定位根节点
indexMap = new HashMap<Integer, Integer>();
for (int i = 0; i < n; i++) {
indexMap.put(inorder[i], i);
}
return myBuildTree(preorder, inorder, 0, n - 1, 0, n - 1);
}
}
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructHelper(nums,0,nums.length-1);//左闭右闭
}
public TreeNode constructHelper(int[] nums,int start,int end){
if(end - start < 0 ){
return null;}//终止条件
int maxIndex = start;
int maxValue = nums[maxIndex];
for (int i =start+1;i<=end;i++){
if(nums[i]>maxValue){
maxValue=nums[i];
maxIndex=i;}
}//找最大值及坐标
TreeNode root = new TreeNode(maxValue);//根节点
root.left = constructHelper(nums,start,maxIndex-1);
root.right = constructHelper(nums,maxIndex+1,end);
return root;
}
}
class Solution {
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;
}
}
class Solution {
TreeNode max;
public boolean isValidBST(TreeNode root) {
if (root==null){return true;}
boolean left = isValidBST(root.left);
if(!left){return false;}
if (max != null && max.val>=root.val ){
return false;
}
max = root;
boolean right = isValidBST(root.right);
if(!right){return false;}
return true;
}
}
class Solution {
public TreeNode searchBST(TreeNode root, int val) {
if (root == null || root.val ==val){
return root;
}
if (root.val>val){
return searchBST(root.left,val);
}
else {
return searchBST(root.right,val);
}
}
}
- 思路
把二叉树变成数组,再求
直接用pre记录上一个节点,进行计算
中序遍历:从小到大
技巧:用一个pre指针指向前一个元素
- 代码
//中序遍历出来是递增序列
class Solution {
int result = Integer.MAX_VALUE;
TreeNode temp;//记录上一个节点
public int getMinimumDifference(TreeNode root) {
if (root==null){return 0;}
getHelper(root);
return result;
}
public void getHelper(TreeNode root){
if (root==null){return;}
getHelper(root.left);//left
if (temp != null){
result = Math.min(result,root.val-temp.val);
}
temp = root;
getHelper(root.right);
}
}
class Solution {
//指针+记录频率变量
int count = 0;//用来计数
int maxCount = 0;//最大频率
ArrayList<Integer> result = new ArrayList<>();//存放结果
TreeNode prev = null;//引入指针 指向前一个元素
public int[] findMode(TreeNode root) {
findHelper(root);
int[] res = new int[result.size()];
for(int i=0;i<result.size();i++){
res[i]=result.get(i);
}
return res;
}
public void findHelper(TreeNode root){
if(root==null){return;}
findHelper(root.left);//处理左树
//记录count
if (prev == null|| prev.val != root.val) { count=1; }
else if (prev.val == root.val){count++;}
//判断count
if(count==maxCount){
result.add(root.val);
}
else if(count>maxCount){
maxCount=count;
result.clear();
result.add(root.val);
}
prev = root;//指针移动
findHelper(root.right);
}
}
class Solution {
int sum = 0;
public TreeNode convertBST(TreeNode root) {
convertHelper(root);
return root;
}
public TreeNode convertHelper(TreeNode root){
if (root == null){return null;}
//右中左
convertHelper(root.right);
sum = sum + root.val;
root.val = sum;
convertHelper(root.left);
return root;
}
}
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//终止条件
if (root==null){return null;}
if (root==p||root==q){return root;}//返回值必然是p或者q
//遍历左右
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
//处理中节点
if (left ==null && right == null) {return null;}
else if (left != null && right == null){return left;}//p和q在左树上
else if (left == null && right != null){return right;}
else{return root;}
}
}
class Solution {
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;
}
}
class Solution {
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root == null){
TreeNode node = new TreeNode(val);
return node;
}
//BST往往不需要遍历整个树
if(root.val>val){root.left=insertIntoBST(root.left,val);}
if(root.val<val){root.right=insertIntoBST(root.right,val);}
return root;
}
}
class Solution {
public TreeNode deleteNode(TreeNode root, int key) {
//终止条件
if (root == null){return null;}
//找到了节点
if (root.val == key){
//1.左右树都为空 直接删除
if (root.left == null && root.right == null){
return null;
}
//2.左为空,右不为空:
if (root.left == null && root.right!=null){
return root.right;
}
//3.左不为空,右为空:
if (root.left != null && root.right == null){
return root.left;
}
//4.左右均非空:把左孩子移到右子树最左面节点的做孩子上
else if(root.left!=null&&root.right!=null){
TreeNode node = root.right;
while(node.left!=null){
node = node.left;
}
node.left = root.left;
root = root.right;
return root;
}
}
if (root.val > key){
root.left = deleteNode(root.left,key);
}
if (root.val < key){
root.right = deleteNode(root.right,key);
}
return root;
}
}
class Solution {
public TreeNode trimBST(TreeNode root, int low, int high) {
if (root == null){return null;}
//单层逻辑
if (root.val<low){//小于最小,遍历右树
return trimBST(root.right,low,high);
}
if (root.val>high){
return trimBST(root.left,low,high);
}
//处于区间之中
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
}
class Solution {
public TreeNode sortedArrayToBST(int[] nums) {
TreeNode node = sortedHelper(nums,0,nums.length-1);
return node;
}
public TreeNode sortedHelper(int[] nums,int left,int right){
if(left>right){return null;}
int mid = left + ((right-left) >> 1);
TreeNode node = new TreeNode(nums[mid]);
node.left = sortedHelper(nums,left,mid-1);
node.right = sortedHelper(nums,mid+1,right);
return node;
}
}