文章目录
理论基础
二叉树是天然的递归结构!
求深度选用前序遍历,求高度选用后序遍历。深度从上至下1 2 3 高度从下至上1 2 3
遍历二叉树
递归遍历
/**
* 递归,先序遍历 leetcode-144
*
* @param root
* @return
*/
public List<Integer> preorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
list.add(root.val);
preorderTraversal(root.left);
preorderTraversal(root.right);
return list;
}
/**
* 递归:中序遍历 leetcode-94
*
* @param root
* @return
*/
public List<Integer> inorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
inorderTraversal(root.left);
list.add(root.val);
inorderTraversal(root.right);
return list;
}
/**
* 后序遍历 leetcode-145
*
* @param root
* @return
*/
public List<Integer> postorderTraversal(TreeNode root) {
if (root == null) return new ArrayList<>();
postorderTraversal(root.left);
postorderTraversal(root.right);
list.add(root.val);
return list;
}
迭代遍历
/**
* 迭代,先序遍历 leetcode-144
*
* @param root
* @return
*/
public List<Integer> preorderTraversal2(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) return list;
//用栈来实现 先入右节点 后入左节点
Deque<TreeNode> stack = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
list.add(node.val);
if(node.right != null) stack.push(node.right);
if(node.left != null) stack.push(node.left);
}
return list;
}
/**
* 迭代:中序遍历 leetcode-94
*
* @param root
* @return
*/
public static List<Integer> inorderTraversal2(TreeNode root) {
List<Integer> list = new ArrayList<>();
if(root == null) return list;
Deque<TreeNode> stack = new LinkedList<>();
TreeNode p = root;
while (!stack.isEmpty() || p!= null) {
//有左入左,没左出栈,入右
while(p != null){
stack.push(p);
p = p.left;
}
p = stack.pop();
list.add(p.val);
p = p.right;
}
return list;
}
/**
* 迭代,后序遍历 leetcode-145
*
* @param root
* @return
*/
public static List<Integer> postorderTraversal2(TreeNode root) {
//后序遍历是左右根 先序遍历是根左右,将其变成根右左,再反转即可得到后序
List<Integer> list = new ArrayList<>();
if(root == null) return list;
Deque<TreeNode> stack = new LinkedList<>();
Deque<TreeNode> res = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()){
TreeNode node = stack.pop();
res.push(node);
if(node.left != null) stack.push(node.left);
if(node.right != null) stack.push(node.right);
}
while (!res.isEmpty()){
list.add(res.pop().val);
}
return list;
}
层次遍历
/**
* 层次遍历
*
* @param root
* @return
*/
public List<List<Integer>> levelOrder(TreeNode root) {
//用队列实现
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> queue = new LinkedList<>();
if (root == null) return res;
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> list = new ArrayList<>();
int len = queue.size();
while (len > 0) {
TreeNode node = queue.poll();
list.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
len--;
}
res.add(list);
}
return res;
}
翻转二叉树
/**
* 反转二叉树leetcode-226
* @param root
* @return
*/
public TreeNode invertTree(TreeNode root) {
//把每个节点的左右子树交换即可
//使用先序遍历 后序和层次遍历均可 中序比较麻烦 有些节点会重复交换
if(root == null) return root;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
对称二叉树
迭代:
/**
* 迭代法,leetcode-101
*
* @param root
* @return
*/
public boolean isSymmetric(TreeNode root) {
//迭代法中只需要把左右子树要比较的节点按顺序加入容器,然后成对地拿出来比较
//用栈、队列、甚至数组均可
//java中双端队列更方便操作
Deque<TreeNode> deque = new LinkedList<>();
if (root == null) return true;
deque.offerFirst(root.left);
deque.offerLast(root.right);
while (!deque.isEmpty()) {
TreeNode leftNode = deque.pollFirst();
TreeNode rightNode = deque.pollLast();
if (leftNode == null && rightNode == null) continue;
if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
return false;
}
deque.offerFirst(leftNode.left);
deque.offerFirst(leftNode.right);
deque.offerLast(rightNode.right);
deque.offerLast(rightNode.left);
}
return true;
}
递归:
/**
* 递归,leetcode-101
*
* @param root
* @return
*/
public boolean isSymmetric2(TreeNode root) {
if (root == null) return true;
return compare(root.left, root.right);
}
public boolean compare(TreeNode leftNode, TreeNode rightNode) {
if (leftNode == null && rightNode == null) return true;
if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) { //有一个空就false
return false;
}
boolean out = compare(leftNode.left, rightNode.right); //外侧是否相等
boolean in = compare(leftNode.right, rightNode.left);//内测是否相等
return out && in; //同时相等才为真
}
类似题目
/**
*相同的树 leetcode-100
* @param p
* @param q
* @return
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null || q ==null || p.val!=q.val){
return false;
}
boolean left = isSameTree(p.left, q.left);
boolean right = isSameTree(p.right,q.right);
return left&&right;
}
/**
* 判断子树 leetcode-572
* @param root
* @param subRoot
* @return
*/
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if (root == null && subRoot == null) return true;
if (root == null || subRoot == null ) { //有一个空就false
return false;
}
boolean res1 = isSameTree(root,subRoot);
boolean res2 = isSubtree(root.left,subRoot);
boolean res3 = isSubtree(root.right,subRoot);
return res1 || res2 || res3;
}
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null || q ==null || p.val!=q.val){
return false;
}
boolean left = isSameTree(p.left, q.left);
boolean right = isSameTree(p.right,q.right);
return left&&right;
}
二叉树最大深度
要注意高度与深度的区别:高度是以最下面叶子节点为水平面,深度是以根节点为水平面
/**
* 递归法-1,二叉树的最大深度 leetcode -104
* @param root
* @return
*/
int max = 0;
public int maxDepth(TreeNode root) {
getDepth(root,0);
return max;
}
public void getDepth(TreeNode root,int depth){
if(root == null) return;
depth++;
max = Math.max(max,depth);//保存最大的深度
getDepth(root.left,depth);
getDepth(root.right,depth);
}
/**
* 递归法-2,二叉树的最大深度 leetcode -104
* @param root
* @return
*/
public int maxDepth2(TreeNode root){
if(root == null) return 0;
int depth1 = maxDepth2(root.left);
int depth2 = maxDepth2(root.right);
return Math.max(depth1,depth2)+1;
}
/**
* 迭代法,二叉树的最大深度 leetcode -104
* @param root
* @return
*/
public int maxDepth3(TreeNode root){
//使用层次遍历
int depth = 0;
if(root == null) return depth;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
while (!deque.isEmpty()){
depth++;
int size = deque.size();
while (size > 0){
TreeNode node = deque.poll();
if(node.left!=null) deque.offer(node.left);
if(node.right!=null) deque.offer(node.right);
size--;
}
}
return depth;
}
二叉树最小深度
/**
* 二叉树的最小深度 leetcode-111
*
* @param root
* @return
*/
public int minDepth(TreeNode root) {
// 最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int high = 0;
while (!deque.isEmpty()) {
int size = deque.size();
high++;
while (size > 0) {
TreeNode node = deque.poll();
if (node.left == null && node.right == null) {
return high;
}
if (node.left != null) deque.offer(node.left);
if (node.right != null) deque.offer(node.right);
size--;
}
}
return high;
}
/**
* 递归法
*
* @param root
* @return
*/
public int minDepth2(TreeNode root) {
//与求最大深度不一样的地方在于 左右孩子有一个为空的情况
if (root == null) return 0;
//左右孩子有一个为空 返回高的
if (root.left == null && root.right != null) return 1 + minDepth2(root.right);
if (root.right == null && root.left != null) return 1 + minDepth2(root.left);
int high1 = minDepth2(root.left);
int high2 = minDepth2(root.right);
return Math.min(high1, high2) + 1;
}
完全二叉树的节点个数
/**
* 迭代,222. 完全二叉树的节点个数
*
* @param root
* @return
*/
public int countNodes(TreeNode root) {
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int res = 0;
while (!deque.isEmpty()) {
int size = deque.size();
res += size;
while (size > 0) {
TreeNode node = deque.poll();
if (node.left != null) deque.offer(node.left);
if (node.right != null) deque.offer(node.right);
size--;
}
}
return res;
}
/**
* 递归-1,222. 完全二叉树的节点个数
*
* @param root
* @return
*/
public int countNodes2(TreeNode root) {
if (root == null) return 0;
List<Integer> list = new ArrayList<>();
count(root, list);
return list.size();
}
public void count(TreeNode root, List<Integer> list) {
if (root == null) return;
list.add(root.val);
count(root.left, list);
count(root.right, list);
}
/**
* 递归-2,222. 完全二叉树的节点个数
*
* @param root
* @return
*/
public int countNodes3(TreeNode root) {
if (root == null) return 0;
int left = countNodes3(root.left);
int right = countNodes3(root.right);
return left + right + 1;
}
判断是否是平衡二叉树
/**
* 判断是否是平衡二叉树 leetcode-110
*
* @param root
* @return
*/
public boolean isBalanced(TreeNode root) {
//获取高度 用后序遍历
return getHeight(root) != -1;
}
public int getHeight(TreeNode root) {
if (root == null) return 0;
int left = getHeight(root.left);
if (left == -1) return -1; //一旦不平衡就返回 递归终止条件
//可以想想根节点的左子树是1 2 3 4 右子树也是1 2 3 4 整个树形状是“^” 显然不平衡 左边不平衡了就直接返回 若不返回 最后得到的结果是平衡
int right = getHeight(root.right);
if (right == -1) return -1;
if (Math.abs(left - right) > 1) { //不平衡
return -1;
} else {
return Math.max(left, right) + 1;
}
}
// 方法2
boolean res = true;
public boolean isBalanced(TreeNode root) {
height(root);
return res;
}
public int height(TreeNode root){
if(root == null) return 0;
int left = height(root.left);
int right = height(root.right);
if(Math.abs(left-right) > 1){
res = false;
}
return Math.max(left,right)+1;
}
二叉树的所有路径
String虽然是引用类型,每次+或者赋值其实都是生成了一个新的String对象,即在递归过程中也不存在分支污染问题,不需要回溯操作
/**
* 递归,返回二叉树的所有路径
* @param root
* @return
*/
public List<String> binaryTreePaths(TreeNode root) {
List<String> list = new ArrayList<>();
if(root == null ) return list;
getPaths(root,list,"");
return list;
}
public void getPaths(TreeNode root,List<String> list,String path){
if(root == null) return;
if(root.left == null && root.right == null) {
list.add( path+root.val);
return;
}
//非叶子节点 遍历它的左右节点
getPaths(root.left,list,path + root.val + "->");
getPaths(root.right,list,path + root.val + "->");
}
/**
* 广度优先
* @param root
* @return
*/
public List<String> binaryTreePaths2(TreeNode root) {
if(root == null) return new ArrayList<>();
List<String> list = new ArrayList<>();
Deque<Object> deque = new LinkedList<>();
deque.offer(root);
deque.offer(root.val + "");
while (!deque.isEmpty()){
TreeNode node = (TreeNode) deque.poll();
String path = (String) deque.poll(); //成对加入
if(node.left == null && node.right == null){
list.add(path);
}
if(node.left != null){
deque.offer(node.left);;
deque.offer(path+"->"+node.left.val);
}
if(node.right != null){
deque.offer(node.right);
deque.offer(path+"->"+node.right.val);
}
}
return list;
}
左叶子节点之和
/**
* 迭代法,左叶子之和 leetcode-404
* @param root
* @return
*/
public int sumOfLeftLeaves(TreeNode root) {
int sum = 0;
if(root == null) return sum;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
while (!deque.isEmpty()){
TreeNode node = deque.poll();
if(node.left != null){
deque.offer(node.left);
if(node.left.left == null && node.left.right == null) sum+=node.left.val;
}
if(node.right != null){
deque.offer(node.right);
}
}
return sum;
}
/**
* 递归,左叶子之和 leetcode-404
* @param root
* @return
*/
int res = 0;
public int sumOfLeftLeaves2(TreeNode root) {
if(root == null) return 0;
if(root.left != null && root.left.left == null && root.left.right == null){
res += root.left.val;
}
sumOfLeftLeaves2(root.left);
sumOfLeftLeaves2(root.right);
return res;
}
public int sumOfLeftLeaves3(TreeNode root) {
int leftVal = sumOfLeftLeaves(root.left); //递归左子树,返回左子树左叶子的值
int rightVal = sumOfLeftLeaves(root.right); //递归右子树,返回右子树左叶子的值
int curLeftVal = 0; //中
if(root.left != null && root.left.left == null && root.left.right == null){
curLeftVal = root.left.val; //左叶子的值
}
return curLeftVal + leftVal + rightVal; //左+右+根 可以联系求深度来理解
}
找树左下角的值
/**
* leetcode-513 找树左下角的值
*
* @param root
* @return
*/
public int findBottomLeftValue(TreeNode root) {
if (root == null) return 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
int res = 0;
while (!deque.isEmpty()) {
int size = deque.size();
res = deque.peek().val;
while (size > 0) {
TreeNode node = deque.poll();
if (node.left != null) deque.offer(node.left);
if (node.right != null) deque.offer(node.right);
size--;
}
}
return res;
}
/**
* leetcode-513 找树左下角的值
*
* @param root
* @return
*/
int max = 0; int res;
public int findBottomLeftValue2(TreeNode root) {
if (root == null) return 0;
//最后一行最左边
dfs(root,1);
return res;
}
void dfs(TreeNode root,int depth){
if(root == null)return;
if(depth > max) {
max = depth;
res = root.val;
}
dfs(root.left,depth+1);
dfs(root.right,depth+1);
}
路径总和
/**
* leetcode-112 路径总和
* @param root
* @param targetSum
* @return
*/
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root == null) return false;
int sum = 0;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root);
while (!deque.isEmpty()){
TreeNode node = deque.poll();
if(node.left == null && node.right == null && node.val == targetSum) return true;
if(node.left != null) {
deque.offer(node.left);
node.left.val += node.val;
}
if(node.right != null) {
deque.offer(node.right);
node.right.val+=node.val;
}
}
return false;
}
/**
* leetcode-112 路径总和
* @param root
* @param targetSum
* @return
*/
public boolean hasPathSum2(TreeNode root, int targetSum) {
if(root == null) return false;
if(root.left == null && root.right == null && root.val == targetSum) return true;
boolean flag = hasPathSum(root.left,targetSum-root.val);
boolean flag2 = hasPathSum(root.right,targetSum-root.val);
return flag || flag2;
}
路径总和2
/**-
* 路径总和2 leetcode -113
* @param root
* @param targetSum
* @return
*/
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
List<List<Integer>> list = new ArrayList<>();
if(root == null) return list;
Deque<TreeNode> dequeNode = new LinkedList<>();
Deque<List<Integer>> dequeList = new LinkedList<>();
List<Integer> subList = new ArrayList<>();
subList.add(root.val);
dequeNode.offer(root);
dequeList.offer(subList);
while (!dequeNode.isEmpty()){
TreeNode node = dequeNode.poll();
List<Integer> tempList = dequeList.poll();
if(node.left == null && node.right == null && node.val == targetSum) {
list.add(tempList);
}
if(node.left != null) {
tempList.add(node.left.val);
dequeNode.offer(node.left);
//list是引用传递 进行修改会影响其他list的值
dequeList.add(new ArrayList<>(tempList));
node.left.val += node.val;
tempList.remove(tempList.size()-1);
}
if(node.right != null) {
dequeNode.offer(node.right);
tempList.add(node.right.val);
dequeList.add(new ArrayList<>(tempList));
node.right.val+=node.val;
}
}
return list;
}
public List<List<Integer>> pathSum2(TreeNode root, int sum) {
List<List<Integer>> result = new ArrayList<>();
dfs(root, sum, new ArrayList<>(), result);
return result;
}
public void dfs(TreeNode root, int sum, List<Integer> list,
List<List<Integer>> result) {
if(root == null) return;
ArrayList<Integer> subList = new ArrayList<>(list);
subList.add(root.val);
if(root.left == null && root.right == null && root.val == sum){
result.add(subList);
}
dfs(root.left,sum-root.val,subList,result);
dfs(root.right,sum-root.val,subList,result);
}
中序和后序构造二叉树
//leetcode-106
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 buildTree2(postorder,0,inorder.length-1,0,postorder.length-1);
}
public TreeNode buildTree2(int[] postorder,int lIn,int rIn,
int lPost,int rPost) {
if(lIn > rIn || lPost > rPost) return null;
int rootVal = postorder[rPost]; //根节点的值
TreeNode root = new TreeNode(rootVal);
//在中序遍历中找到根
int index =map.get(rootVal);
// 中序数组大小一定是和后序数组的大小相同的
root.left = buildTree2(postorder,lIn,index-1,lPost,lPost+index-lIn-1);
root.right = buildTree2(postorder,index+1,rIn,lPost+index-lIn,rPost-1);
return root;
}
最大二叉树
//leetcode-654
public TreeNode constructMaximumBinaryTree(int[] nums) {
return buildTree(0,nums.length-1,nums);
}
public TreeNode buildTree(int start,int end ,int[] nums){
if(end < start) return null;
int maxIndex = getMaxIndex(start, end, nums);
TreeNode root = new TreeNode(nums[maxIndex]);
root.left = buildTree(start,maxIndex-1,nums);
root.right = buildTree(maxIndex+1,end,nums);
return root;
}
public int getMaxIndex(int start,int end ,int[] nums){
int max = nums[start];
int maxIndex = start;
for (int i = start; i <= end; i++) {
if(nums[i] > max){
max = nums[i];
maxIndex = i;
}
}
return maxIndex;
}
合并二叉树
/**
* leetcode-617
* @param root1
* @param root2
* @return
*/
public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
if(root1 == null) return root2;
if(root2 == null) return root1;
Deque<TreeNode> deque = new LinkedList<>();
deque.offer(root1);
deque.offer(root2);
while (!deque.isEmpty() ){
TreeNode node1 = deque.poll();
TreeNode node2 = deque.poll();
node1.val+=node2.val;
if(node1.left != null && node2.left!= null){
deque.offer(node1.left);
deque.offer(node2.left);
} else if (node1.left == null) { // 树1 的左子树为空 直接把树2 的左子树拿过来挂着
node1.left = node2.left;
}
if(node1.right != null && node2.right!= null){
deque.offer(node1.right);
deque.offer(node2.right);
} else if (node1.right == null) {
node1.right = node2.right;
}
}
return root1;
}
/**
* 递归
* @param root1
* @param root2
* @return
*/
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;
}
}
二叉搜索树中的搜索
/**
* leetcode-700. 二叉搜索树中的搜索
* @param root
* @param val
* @return
*/
public TreeNode searchBST(TreeNode root, int val) {
if(root == null) return root;
if(val > root.val ){
return searchBST(root.right,val); //搜索到了结果就要返回 不然返回值没了
}else if(val < root.val){
return searchBST(root.left,val);
}else{
return root;
}
}
public TreeNode searchBST2(TreeNode root, int val) {
if(root == null) return root;
while (root != null && root.val != val){
if(val > root.val ) root = root.right;
else {
root = root.left;
}
}
return root;
}
是否是二叉搜索树
/**
* 验证是否是二叉搜索树 leetcode-98
*
* @param root
* @return
*/
long max = Long.MIN_VALUE;
public boolean isValidBST(TreeNode root) {
//二叉排序树的后序是有序序列
if (root == null) return true;
// 不能像这样单纯的比较 因为左子树的所有节点均小于根节点 ……
// if(root.left.val < root.val && root.right.val > root.val){
// return true;
// }
boolean left = isValidBST(root.left);
if (root.val > max) max = root.val;
else return false;
boolean right = isValidBST(root.right);
return left && right;
}
//方法2
TreeNode pre = null;
public boolean isValidBST(TreeNode root) {
if(root == null) return true;
boolean left = isValidBST(root.left);
if(pre != null && root.val <= pre.val) return false;
pre = root;
boolean right = isValidBST(root.right);
return left&&right;
}
二叉搜索树的最小绝对误差
/**
* leetcode-530. 二叉搜索树的最小绝对差
* @param root
* @return
*/
int min = Integer.MAX_VALUE;
public int getMinimumDifference(TreeNode root) {
if(root ==null) return 0;
inOrder(root);
return min;
}
TreeNode pre = null;
public void inOrder(TreeNode root){
if (root == null) return ;
inOrder(root.left);
if(pre != null)
min = Math.min(root.val-pre.val,min);
pre = root;
inOrder(root.right);
}
二叉搜索树中的众数
/**
* 501. 二叉搜索树中的众数
* @param root
* @return
*/
TreeNode pre = null;
List<Integer> list = new ArrayList<>();
int count = 0;
int maxCount = 0; //记录最大值
public int[] findMode(TreeNode root) {
if(root == null) return new int[]{};
inOrder(root);
int[] res = new int[list.size()];
for (int i = 0; i < list.size(); i++) {
res[i] = list.get(i);
}
return res;
}
public void inOrder(TreeNode root){
if(root == null) return;
inOrder(root.left);
if(pre == null || pre.val != root.val){
count=1;
}else count++;
if(count > maxCount){ //有更大频率的就清空list 并将当前最大添加到list
list.clear();
maxCount = count;
list.add(root.val);
}else if(count == maxCount){
list.add(root.val);
}
pre = root;
inOrder(root.right);
}
二叉树的最近公共祖先
/**
* 236. 二叉树的最近公共祖先
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
// 如果 root == q,或者 root == p,说明找到 q p ,则将其返回
if(root == null || p == root || q == root) return root;
//后序
TreeNode left = lowestCommonAncestor(root.left, p, q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
//如果 左右子树的返回值都不为空,说明此时的根节点,一定是q 和p 的最近祖先。
//另一种情况 根节点5 它的左子树3 找它们的最近公共祖先 此类情况已被上面方案包含
if(root.left != null && root.right != null) return root;
if(root.left != null)return left; //哪个不为空就往上返回
else {
return right;
}
}
二叉搜索树的最近公共祖先
/**
* 递归 leetcode-235 二叉搜索树的最近公共祖先
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor4(TreeNode root, TreeNode p, TreeNode q) {
if(p.val < root.val && q.val < root.val){
return lowestCommonAncestor(root.left,p,q); //搜索到了结果就要返回
}else if(p.val > root.val && q.val > root.val){
return lowestCommonAncestor(root.right,p,q);
}
return root;
}
/**
* leetcode-235 二叉搜索树的最近公共祖先
* @param root
* @param p
* @param q
* @return
*/
TreeNode res = null;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//深度遍历 若遍历的当前节点的值介于p和q之间则可以直接返回 因为是二叉搜索树
// p和q不一定谁大
if(p.val < q.val) dfs(root,p,q);
else dfs(root,q,p);
return res;
}
public void dfs(TreeNode root,TreeNode p, TreeNode q){
if(root == null) return;
if(p.val <= root.val && root.val <= q.val){
res = root;
return;
}
dfs(root.left,p,q);
dfs(root.right,p,q);
}
/**
* 迭代 leetcode-235 二叉搜索树的最近公共祖先
* @param root
* @param p
* @param q
* @return
*/
public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode p, TreeNode q) {
while (root != null){
if(root.val > p.val && root.val > q.val){
root = root.left;
} else if (root.val < p.val && root.val < q.val) {
root = root.right;
}else{
return root;
}
}
return root;
}
二叉搜索树中的插入操作
/**
* leetcode-701 二叉搜索树中的插入
* @param root
* @param val
* @return
*/
public TreeNode insertIntoBST(TreeNode root, int val) {
if(root == null) return new TreeNode(val);
TreeNode res = root;
while (true){
if(val >root.val){
if(root.right != null) root = root.right;
else {
root.right = new TreeNode(val);
break;
}
}else {
if(root.left != null) root = root.left;
else {
root.left = new TreeNode(val);
break;
}
}
}
return res;
}
//递归
public TreeNode insertIntoBST(TreeNode root, int val) {
// 终止条件就是找到遍历的节点为null的时候,就是要插入节点的位置了,并把插入的节点返回。
if(root == null){
TreeNode node = new TreeNode(val);
return node; //这里把添加的节点返回给上一层,就完成了父子节点的赋值操作了
}
// 下一层将加入节点返回,本层用root->left或者root->right将其接住。
if(root.val > val) root.left = insertIntoBST(root.left,val);
if(root.val < val) root.right = insertIntoBST(root.right,val);
return root;
}
删除二叉搜索树中的节点
/**
* leetcode-450 删除二叉搜索树中的节点
* @param root
* @param key
* @return
*/
public TreeNode deleteNode(TreeNode root, int key) {
/*要删除的节点无左右孩子 即叶子节点 最简单 直接删除即可
要删除的节点只有左孩子 左孩子替换当前节点
要删除的节点只有右孩子 右孩子替换当前节点
要删除的节点有左、右孩子 把左孩子放在 待删除节点右孩子最左边节点的左孩子上
二叉搜索树后序是有序序列 待删除节点右孩子的最左边即是待删除节点的下一节点*/
//迭代法更繁琐一些
if(root == null) return root;
if(key < root.val) root.left = deleteNode(root.left,key);
else if(key > root.val) root.right = deleteNode(root.right,key);
else {
if(root.left == null && root.right == null) return null;
else if (root.left == null) {
return root.right;
}else if(root.right == null){
return root.left;
}else {
TreeNode temp = root.right;
while (temp.left != null){
temp = temp.left;
}
temp.left = root.left;
return root.right;
}
}
return root;
}
修剪二叉搜索树
/**
* leetcode-669 修剪二叉搜索树
* @param root
* @param low
* @param high
* @return
*/
public TreeNode trimBST(TreeNode root, int low, int high) {
if(root == null) return root;
if(root.val < low) {
//return root.right; 不应该直接返回右子树 因为右子树中也有不符合条件的元素
return trimBST(root.right,low,high); //而是应该继续往右子树寻找可用的节点
}
if(root.val > high) {
//return root.left;
return trimBST(root.left,low,high);
}
root.left = trimBST(root.left,low,high);
root.right = trimBST(root.right,low,high);
return root;
}
将有序数组转换为二叉搜索树
/**
* leetcode-108. 将有序数组转换为二叉搜索树
* @param nums
* @return
*/
public TreeNode sortedArrayToBST(int[] nums) {
return sort(nums,0,nums.length-1);
}
public TreeNode sort(int[] nums,int start,int end){
if(end < start) return null;
int mid = (start+end)/2;
TreeNode root = new TreeNode(nums[mid]);
root.left = sort(nums,start,mid-1);
root.right = sort(nums,mid+1,end);
return root;
}
把二叉搜索树转换为累加树
/**
* leetcode-538. 把二叉搜索树转换为累加树
* @param root
* @return
*/
int pre = 0;
public TreeNode convertBST(TreeNode root) {
if(root ==null) return root;
pre(root);
return root;
}
public void pre(TreeNode root){
if(root == null) return;
//先右 后中 再左
pre(root.right);
root.val += pre;
pre = root.val;
pre(root.left);
}