代码随想录刷题-二叉树

文章目录

    • 1.二叉树的遍历方式
      • 2-144.二叉树的递归遍历🟢
      • 3-144.二叉树的迭代遍历🟢
      • 5-102.二叉树的层序遍历🟡
    • 2.求二叉树的属性
      • 8-101.对称二叉树🟢
      • 9-104.二叉树的最大深度🟢
      • 10-111.二叉树的最小深度🟢
      • 11-222.完全二叉树的节点个数🟢
      • 12-110.平衡二叉树🟢
      • 13-257.二叉树的所有路径🟢
      • 15-404.左叶子之和🟢
      • 16-513.找树左下角的值🟡
      • 17-112.路径总和🟢
    • 3.二叉树的修改与构造
      • 6-226.翻转二叉树🟢
      • 18-106.从中序与后序遍历序列构造二叉树🟡
      • 19-654.最大二叉树🟡
      • 21-617.合并二叉树🟢
    • 4.二叉树公共祖先问题
      • 26-236.二叉树的最近公共祖先🟡
      • 28-235.二叉搜索树的最近公共祖先🟡
    • 5.求二叉搜索树的属性
      • 22-700.二叉搜索树中的搜索🟢
      • 23-98.验证二叉搜索树🟡
      • 24-530.二叉搜索树的最小绝对差🟢
      • 25-501.二叉搜索树中的众数🟢
    • 6.二叉搜索树的修改与构造
      • 29-701.二叉搜索树中的插入操作🟡
      • 30-450.删除二叉搜索树中的节点🟡
      • 31-669.修剪二叉搜索树🟡
      • 32-108.将有序数组转换为二叉搜索树🟡
      • 33-538.把二叉搜索树转换为累加树🟡

1.二叉树的遍历方式

2-144.二叉树的递归遍历🟢

题目:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

链接:144. 二叉树的前序遍历

代码:

class Solution {  public List<Integer> preorderTraversal(TreeNode root) {  List<Integer> res = new ArrayList<Integer>();  traversal(root, res);  return res;  }  public void traversal(TreeNode root, List<Integer> res) {  if (root == null) {  return;  }  res.add(root.val); // 中(放到中间就是中序遍历,放到最下边就是后序遍历)traversal(root.left, res); // 左 traversal(root.right, res);  // 右}  
}

3-144.二叉树的迭代遍历🟢

题目:给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

链接:144. 二叉树的前序遍历

代码:

class Solution {// 前序遍历顺序:中-左-右,入栈顺序:中-右-左// 首先将根入栈,因为栈是FILO,所以要先将右结点入栈,再将左结点入栈public List<Integer> preorderTraversal(TreeNode root) {List<Integer> res = new LinkedList<>();Deque<TreeNode> stack = new LinkedList<>();if (root == null) return res;stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop(); // 中res.add(node.val);if (node.right != null) {stack.push(node.right); // 右}if (node.left != null) {stack.push(node.left);  // 左}}return res;}
}

后序迭代方式遍历代码:

class Solution {public List<Integer> postorderTraversal(TreeNode root) {// 前序遍历返回的res是根左右,如果调换while中右左入栈的顺序// 就会得到根右左顺序的res,将res反转就会得到左右根List<Integer> res = new LinkedList<>();if (root == null) return res;Deque<TreeNode> stack = new LinkedList<>();stack.push(root);while (!stack.isEmpty()) {TreeNode node = stack.pop();  // 中res.add(node.val);if (node.left != null) {stack.push(node.left); // 左}if (node.right != null) {stack.push(node.right);  // 右}}Collections.reverse(res); // 反转return res;}
}

中序迭代方式遍历代码:

class Solution {public List<Integer> inorderTraversal(TreeNode root) {// 首先判断当前结点是否为空,不为空将当前结点的左结点入栈,// 若为空,取栈顶元素加入res,将栈顶元素的右结点作为当前结点// 继续重复上面步骤,直到当前结点为空且栈为空为止。List<Integer> res = new LinkedList<>();if (root == null) return res;Deque<TreeNode> stack = new LinkedList<>();TreeNode node = root;while (node != null || !stack.isEmpty()) {if (node != null) {stack.push(node);node = node.left;} else {node = stack.pop();res.add(node.val);node = node.right;}}return res;}
}

5-102.二叉树的层序遍历🟡

题目:给你二叉树的根节点 root ,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。

链接:二叉树的层序遍历

代码:

class Solution {  public List<List<Integer>> levelOrder(TreeNode root) {  List<List<Integer>> res = new LinkedList<>();  if (root == null) {  return res;  }  Queue<TreeNode> q = new LinkedList<>();  q.offer(root);  // while 循环控制从上向下一层层遍历  while (!q.isEmpty()) {  int len = q.size();  // 记录这一层的节点值  List<Integer> level = new LinkedList<>();  // for 循环控制每一层从左向右遍历  for (int i = 0; i < len; i++) {  TreeNode cur = q.poll();  level.add(cur.val);  if (cur.left != null)  q.offer(cur.left);  if (cur.right != null)  q.offer(cur.right);  }  res.add(level);  }  return res;  }  
}

2.求二叉树的属性

8-101.对称二叉树🟢

题目:给你一个二叉树的根节点 root ,检查它是否轴对称。

链接:101. 对称二叉树

代码:

class Solution {public boolean isSymmetric(TreeNode root) {// 对称二叉树,对称的是根的左右子树// 不能完全遍历左右子树之后比较遍历结果,因为不能区分左结点或右结点为空的情况// 左子树通过根左右的方式遍历// 右子树通过根右左的方式遍历// 若左右子树遍历的结果相同,则是对称二叉树TreeNode left = root.left;TreeNode right = root.right;return inorder(left, right);}public boolean inorder(TreeNode left, TreeNode right) {if (left == null && right != null) return false;if (left != null && right == null) return false;if (left == null && right == null) return true;if (left.val != right.val) return false;//前序遍历boolean f1 = inorder(left.left, right.right);boolean f2 = inorder(left.right, right.left);return f1 && f2;}
}

9-104.二叉树的最大深度🟢

题目:给定一个二叉树 root ,返回其最大深度。

二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。

链接:104. 二叉树的最大深度

代码:

class Solution {public int maxDepth(TreeNode root) {// 求二叉树的深度本质上是遍历二叉树// 这里使用后序遍历求二叉树的深度if (root == null) return 0;int leftDepth = maxDepth(root.left);int rightDepth = maxDepth(root.right);return 1 + Math.max(leftDepth, rightDepth);}
}

10-111.二叉树的最小深度🟢

题目:给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

链接:111. 二叉树的最小深度

代码:

class Solution {/*** 递归法,相比求MaxDepth要复杂点* 因为最小深度是从根节点到最近叶子节点的最短路径上的节点数量*/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;}// 左右结点都不为nullreturn Math.min(leftDepth, rightDepth) + 1;}
}

11-222.完全二叉树的节点个数🟢

题目:给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

链接:222. 完全二叉树的节点个数

代码:

1.通用解法

class Solution {// 通用递归解法public int countNodes(TreeNode root) {if (root == null) {return 0;}return countNodes(root.left) + countNodes(root.right) + 1;}
}

2.针对完全二叉树的解法

class Solution {// 满二叉树的结点数为:2^depth - 1public int countNodes(TreeNode root) {if (root == null) return 0;TreeNode left = root.left;TreeNode right = root.right;int leftDepth = 0, rightDepth = 0; // 这里初始为0是有目的的,为了下面求指数方便while (left != null) {  // 求左子树深度left = left.left;leftDepth++;}while (right != null) { // 求右子树深度right = right.right;rightDepth++;}if (leftDepth == rightDepth) {return (2 << leftDepth) - 1; // 注意(2<<1) 相当于2^2,所以leftDepth初始为0}return countNodes(root.left) + countNodes(root.right) + 1;}
}

12-110.平衡二叉树🟢

题目:给定一个二叉树,判断它是否是高度平衡的二叉树

链接:110. 平衡二叉树

代码:

class Solution {  public boolean isBalanced(TreeNode root) {   return height(root) >= 0;  }  // 定义:给一个根节点,返回它的高度,负数代表该树不平衡public int height(TreeNode root) {  if (root == null) {  return 0;  }  int leftHeight = height(root.left);  int rightHeight = height(root.right);  // 如果高度差大于1返回-1表示当前子树不平衡  // 上一级的父节点获取到子节点返回的-1后也返回-1,表示父节点同样也是不平衡的  if (leftHeight == -1 || rightHeight == -1 || Math.abs(leftHeight - rightHeight) > 1) {  return -1;  } else {  return Math.max(leftHeight, rightHeight) + 1;  }  }  
}

13-257.二叉树的所有路径🟢

题目:给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

链接:二叉树的所有路径

代码:

class Solution {  List<String> res = new ArrayList<>();  public List<String> binaryTreePaths(TreeNode root) {  if(root == null) return new ArrayList<>();  // 参数:根节点 当前遍历路径  traversal(root, "");  return res;  }  public void traversal(TreeNode root, String path) {  // 递归结束条件是遇到叶子节点,则将当前路径添加到结果中  if(root.left == null && root.right == null){  res.add(new StringBuilder(path).append(root.val).toString());  return;  }  String tmp = new StringBuilder(path).append(root.val).append("->").toString();  if(root.left != null) traversal(root.left,tmp);  if(root.right != null) traversal(root.right,tmp);  }  
}

15-404.左叶子之和🟢

题目:给定二叉树的根节点 root ,返回所有左叶子之和。

链接:左叶子之和

代码:

class Solution {  int res =0;  public int sumOfLeftLeaves(TreeNode root) {  traversal(root);  return res;  }  public void traversal(TreeNode root){  if(root == null){  return;  }  // 前序遍历,判断当前根节点的左子节点是不是左叶子  if(root.left!=null&&root.left.left==null&&root.left.right==null){  res += root.left.val;  }  traversal(root.left);  traversal(root.right);  }  
}

16-513.找树左下角的值🟡

题目:给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。假设二叉树中至少有一个节点。

链接:找树左下角的值

代码:

1.递归解法(不推荐)

class Solution {  int maxDeep = -1;  int res = 0;  public int findBottomLeftValue(TreeNode root) {  traversal(root,0);  return res;  }  public void traversal (TreeNode root,int deep) {  if (root == null)  return;// 遇到叶子节点开始判断  if (root.left == null && root.right == null) {  // 先左后右,所以可以直接判断当前高度是否大于最大高度  if (deep > maxDeep) {  res = root.val;  maxDeep = deep;  }  }  traversal(root.left,deep + 1);  traversal(root.right,deep + 1);  }  
}

2.迭代解法(推荐)

class Solution {  public int findBottomLeftValue(TreeNode root) {  int res = root.val;  Queue<TreeNode> q = new LinkedList<>();  q.offer(root);  // while 循环控制从上向下一层层遍历  while (!q.isEmpty()) {  int len = q.size();  // for 循环控制每一层从左向右遍历  for (int i = 0; i < len; i++) {  TreeNode cur = q.poll();  // 这一层的第一个节点也就是最左边的  if(i == 0){  res = cur.val;  }  if (cur.left != null)  q.offer(cur.left);  if (cur.right != null)  q.offer(cur.right);  }  }  return res;  }  
}

17-112.路径总和🟢

题目:给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

链接:路径总和

代码:

1.我的解法(易理解但不推荐)

class Solution {  boolean res = false;  public boolean hasPathSum(TreeNode root, int targetSum) {  traversal(root,0,targetSum);  return res;  }// 对树做前序遍历,但若找到则不再进行后续遍历  public void traversal(TreeNode root,int sum,int targetSum){  // 节点为空或已经找到了路径就直接返回// 我是手动判断下!res时不再递归,但可以给函数设置返回值停止后续递归  if(root == null || res){  return;  }  // 是叶子节点且累加值等于目标值  if(root.left == null && root.right == null && root.val+sum == targetSum){  res = true;  }  int tmp = root.val+sum;  traversal(root.left,tmp,targetSum);  traversal(root.right,tmp,targetSum);  }  
}

2.官方解法(推荐)

class Solution {  public boolean hasPathSum(TreeNode root, int sum) {  if (root == null) {  return false;  }  // 碰到叶子节点判断当前剩余值是否等于叶子节点值  if (root.left == null && root.right == null) {  return sum == root.val;  }  // 在递归函数里操作sum,相当于返回的时候会回溯到之前的状态// 如果左子树或右子树中找到了路径就直接返回true,程序就不再继续遍历剩下路径了  return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val);  }  
}

扩展:113.路径总和

题目:给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

链接:路径总和 II

代码:

class Solution {  List<List<Integer>> res = new LinkedList<List<Integer>>();  Deque<Integer> path = new LinkedList<Integer>();  public List<List<Integer>> pathSum(TreeNode root, int targetSum) {  traversal(root, targetSum);  return res;  }  public void traversal(TreeNode root, int targetSum) {  if (root == null) {  return;  }  path.offerLast(root.val);  targetSum -= root.val;  if (root.left == null && root.right == null && targetSum == 0) {  res.add(new LinkedList<Integer>(path));  }  traversal(root.left, targetSum);  traversal(root.right, targetSum);  // 弹出一个元素相当于回溯到之前的状态  path.pollLast();  }  
}

3.二叉树的修改与构造

6-226.翻转二叉树🟢

题目:给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。

链接:226. 翻转二叉树

代码:

class Solution {public TreeNode invertTree(TreeNode root) {// 翻转二叉树,实际上就是交换左右结点// 使用递归来交换,根左右if(root == null) return null;swapChildren(root);invertTree(root.left);invertTree(root.right);return root;}public void swapChildren(TreeNode root){TreeNode temp = root.right;root.right = root.left;root.left = temp;}
}

18-106.从中序与后序遍历序列构造二叉树🟡

题目:给定两个整数数组 inorderpostorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树

链接:从中序与后序遍历序列构造二叉树

代码:

class Solution {  // 存储 inorder 中值到索引的映射  HashMap<Integer, Integer> valToIndex = new HashMap<>();  public TreeNode buildTree(int[] inorder, int[] postorder) {  for (int i = 0; i < inorder.length; i++) {  valToIndex.put(inorder[i], i);  }  return build(inorder, 0, inorder.length - 1,  postorder, 0, postorder.length - 1);  }  /*  定义:  中序遍历数组为 inorder[inStart..inEnd],  后序遍历数组为 postorder[postStart..postEnd],  构造这个二叉树并返回该二叉树的根节点  */    public TreeNode build(int[] inorder, int inStart, int inEnd,  int[] postorder, int postStart, int postEnd) {  if (inStart > inEnd) {  return null;  }  // root 节点对应的值就是后序遍历数组的最后一个元素  int rootVal = postorder[postEnd];  // rootVal 在中序遍历数组中的索引  int index = valToIndex.get(rootVal);  // 左子树的节点个数  int leftSize = index - inStart;  TreeNode root = new TreeNode(rootVal);  // 递归构造左右子树  root.left = build(inorder, inStart, index - 1,  postorder, postStart, postStart + leftSize - 1);  root.right = build(inorder, index + 1, inEnd,  postorder, postStart + leftSize, postEnd - 1);  return root;  }  
}

19-654.最大二叉树🟡

题目:给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 最大二叉树

链接:最大二叉树

代码:

class Solution {/* 主函数 */public TreeNode constructMaximumBinaryTree(int[] nums) {return build(nums, 0, nums.length - 1);}/* 定义:将 nums[lo..hi] 构造成符合条件的树,返回根节点 */public TreeNode build(int[] nums, int lo, int hi) {if (lo > hi) {return null;}// 找到数组中的最大值和对应的索引int index = -1, maxVal = Integer.MIN_VALUE;for (int i = lo; i <= hi; i++) {if (maxVal < nums[i]) {index = i;maxVal = nums[i];}}TreeNode root = new TreeNode(maxVal);// 递归调用构造左右子树root.left = build(nums, lo, index - 1);root.right = build(nums, index + 1, hi);return root;}
}

21-617.合并二叉树🟢

题目:给你两棵二叉树: root1root2

想象一下,当你将其中一棵覆盖到另一棵之上时,两棵树上的一些节点将会重叠(而另一些不会)。你需要将这两棵树合并成一棵新二叉树。合并的规则是:如果两个节点重叠,那么将这两个节点的值相加作为合并后节点的新值;否则,不为 null 的节点将直接作为新二叉树的节点。

返回合并后的二叉树。注意: 合并过程必须从两个树的根节点开始。

链接:617. 合并二叉树

代码:

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;  }  
}

4.二叉树公共祖先问题

26-236.二叉树的最近公共祖先🟡

题目:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

链接:236. 二叉树的最近公共祖先

代码:

class Solution {// 定义:输入三个参数 root,p,q,根据左右子树遍历结果返回一个节点public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {// 递归结束条件if (root == null || root == p || root == q) {return root;}TreeNode left = lowestCommonAncestor(root.left, p, q);TreeNode right = lowestCommonAncestor(root.right, p, q);// 情况 1if (left != null && right != null) {return root;}// 情况 2if (left == null && right == null) {return null;}// 情况 3return left == null ? right : left;}
}

28-235.二叉搜索树的最近公共祖先🟡

题目:给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。

链接:235. 二叉搜索树的最近公共祖先

代码:

1.递归解法

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;}
}

2.迭代解法

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {while (true) {// 如果当前节点比两个待查节点大,就往左子树找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 {break;}}return root;}
}

5.求二叉搜索树的属性

22-700.二叉搜索树中的搜索🟢

题目:给定二叉搜索树(BST)的根节点 root 和一个整数值 val

你需要在 BST 中找到节点值等于 val 的节点。 返回以该节点为根的子树。 如果节点不存在,则返回 null

链接:700. 二叉搜索树中的搜索

代码:

1.递归解法

class Solution {  public TreeNode searchBST(TreeNode root, int val) {  if (root == null || root.val == val) {  return root;  }  // 目标值小于当前值则去左子树搜索  if (val < root.val) {  return searchBST(root.left, val);  }  // 目标值大于当前值则去右子树搜索  if (val > root.val) {  return searchBST(root.right, val);  }  return root;  }  
}

2.迭代解法

class Solution {  // 利用二叉搜索树特点,优化,可以不需要栈  public TreeNode searchBST(TreeNode root, int val) {  while (root != null)  if (val < root.val) {  root = root.left;  } else if (val > root.val) {  root = root.right;  } else return root;  return null;  }  
}

23-98.验证二叉搜索树🟡

题目:给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

有效 二叉搜索树定义如下:

  • 节点的左子树只包含 小于 当前节点的数。
  • 节点的右子树只包含 大于 当前节点的数。
  • 所有左子树和右子树自身必须也是二叉搜索树。

链接:98. 验证二叉搜索树

代码:

class Solution {  // 记录前一个节点的值  public long prev = Long.MIN_VALUE;  // 二叉搜索树中序遍历得到的是一个递增的序列,也可以用一个数组记录再判断数组是否递增  public boolean isValidBST(TreeNode root) {  if (root == null) {  return true;  }  if (!isValidBST(root.left)) {  return false;  }  // 当前节点小于等于前一个节点的值则不满足二叉搜索树条件  if (root.val <= prev) {  return false;  }  prev = root.val;  return isValidBST(root.right);  }  
}

24-530.二叉搜索树的最小绝对差🟢

题目:给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值

差值是一个正数,其数值等于两值之差的绝对值。

链接:530. 二叉搜索树的最小绝对差

代码:

class Solution {  TreeNode prev = null;  int res = Integer.MAX_VALUE;  public int getMinimumDifference(TreeNode root) {  traverse(root);  return res;  }  void traverse(TreeNode root) {  if (root == null) {  return;  }  traverse(root.left);  // 中序遍历位置  if (prev != null) {  // 记录最小值  res = Math.min(res, root.val - prev.val);  }  prev = root;traverse(root.right);  }  
}

25-501.二叉搜索树中的众数🟢

题目:给你一个含重复值的二叉搜索树(BST)的根节点 root ,找出并返回 BST 中的所有 众数(即,出现频率最高的元素)。

如果树中有不止一个众数,可以按 任意顺序 返回。

假定 BST 满足如下定义:

  • 结点左子树中所含节点的值 小于等于 当前节点的值
  • 结点右子树中所含节点的值 大于等于 当前节点的值
  • 左子树和右子树都是二叉搜索树

链接:501. 二叉搜索树中的众数

代码:

class Solution {  ArrayList<Integer> resList = new ArrayList<>();  public int maxCount = 0;  public int count = 0;  public TreeNode pre = null;  public int[] findMode(TreeNode root) {  traversal(root);// 将resList的元素拷贝到res数组中  int[] res = new int[resList.size()];  for (int i = 0; i < resList.size(); i++) {  res[i] = resList.get(i);  }  return res;  }  public void traversal(TreeNode root) {  if (root == null) {  return;  }  traversal(root.left);  // 计数  if (pre == null || root.val != pre.val) {  count = 1;  } else {  count++;  }  // 更新结果以及maxCount  if (count > maxCount) {  resList.clear();  resList.add(root.val);  maxCount = count;  } else if (count == maxCount) {  resList.add(root.val);  }  // 记录前一个节点  pre = root;  traversal(root.right);  }  
}

6.二叉搜索树的修改与构造

29-701.二叉搜索树中的插入操作🟡

题目:给定二叉搜索树(BST)的根节点 root 和要插入树中的值 value ,将值插入二叉搜索树。 返回插入后二叉搜索树的根节点。 输入数据 保证 ,新值和原始二叉搜索树中的任意节点值都不同。

链接:701. 二叉搜索树中的插入操作

代码:

class Solution {public TreeNode insertIntoBST(TreeNode root, int val) {// 找到空位置返回待插入节点if (root == null) {return new TreeNode(val);}if (root.val < val) {// 插入节点操作,insertIntoBST函数返回值就是待插入节点root.right = insertIntoBST(root.right, val);}if (root.val > val) {root.left = insertIntoBST(root.left, val);}// 返回根节点给上一层return root;}
}

30-450.删除二叉搜索树中的节点🟡

题目:给定一个二叉搜索树的根节点 root 和一个值 key,删除二叉搜索树中的 key 对应的节点,并保证二叉搜索树的性质不变。返回二叉搜索树(有可能被更新)的根节点的引用。

链接:450. 删除二叉搜索树中的节点

代码:

1.代码随想录解法:左子树添加到右子树最左边,返回删除节点右孩子为新的当前根节点

class Solution {public TreeNode deleteNode(TreeNode root, int key) {//分为五种情况:// 1.未找到,直接返回rootif (root == null) return root;if (root.val == key) {// 2.找到的节点左子树为空,右子树非空,右子树补上if (root.left == null && root.right != null) {return root.right;// 3.找到的节点右子树为空,左子树非空,左子树补上} else if (root.left != null && root.right == null) {return root.left;// 4.找到的节点左右子树都为空,直接删除} else if (root.left == null && root.right == null) {return null;// 5.找到的节点左右子树都非空,左子树添加到右子树最左边,// 返回删除节点右孩子为新的根节点} else {TreeNode node = root.right;while (node.left != null) {node = node.left;}node.left = root.left;return root.right;}}if (root.val > key) root.left = deleteNode(root.left, key);if (root.val < key) root.right = deleteNode(root.right, key);return root;}
}

2.labuladong 解法:右子树最小节点替换待删节点,再把待删节点删了

class Solution {public TreeNode deleteNode(TreeNode root, int key) {if (root == null) return null;if (root.val == key) {// 这两个 if 把情况 1 和 2 都正确处理了if (root.left == null) return root.right;if (root.right == null) return root.left;// 处理情况 3// 获得右子树最小的节点TreeNode minNode = getMin(root.right);// 删除右子树最小的节点root.right = deleteNode(root.right, minNode.val);// 用右子树最小的节点替换 root 节点minNode.left = root.left;minNode.right = root.right;root = minNode;} else if (root.val > key) {root.left = deleteNode(root.left, key);} else if (root.val < key) {root.right = deleteNode(root.right, key);}return root;}TreeNode getMin(TreeNode node) {// BST 最左边的就是最小的while (node.left != null) node = node.left;return node;}
}

31-669.修剪二叉搜索树🟡

题目:给你二叉搜索树的根节点 root ,同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树,使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即,如果没有被移除,原有的父代子代关系都应当保留)。 可以证明,存在 唯一的答案

所以结果应当返回修剪好的二叉搜索树的新的根节点。注意,根节点可能会根据给定的边界发生改变。

链接:669. 修剪二叉搜索树

代码:

class Solution {// 函数定义:满足区间返回root,不满足则返回root的符合条件的子节点public TreeNode trimBST(TreeNode root, int low, int high) {if (root == null) {return null;}if (root.val < low) {// 当前节点比low小那就去右边寻找符合区间[low, high]的节点return trimBST(root.right, low, high);}if (root.val > high) {return trimBST(root.left, low, high);}// root.left接入符合条件的左孩子root.left = trimBST(root.left, low, high);root.right = trimBST(root.right, low, high);return root;}
}

32-108.将有序数组转换为二叉搜索树🟡

题目:给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵平衡二叉搜索树。

链接:108. 将有序数组转换为二叉搜索树

代码:

class Solution {public TreeNode sortedArrayToBST(int[] nums) {TreeNode root = traversal(nums, 0, nums.length - 1);return root;}// 左闭右闭区间[left, right]// 函数定义:根据数组和给定区间构造root的左右节点private TreeNode traversal(int[] nums, int left, int right) {if (left > right) return null;int mid = left + ((right - left) >> 1); // 防止溢出TreeNode root = new TreeNode(nums[mid]);root.left = traversal(nums, left, mid - 1);root.right = traversal(nums, mid + 1, right);return root;}
}

33-538.把二叉搜索树转换为累加树🟡

题目:给出二叉 搜索 树的根节点,该树的节点值各不相同,请你将其转换为累加树(Greater Sum Tree),使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。

链接: 538. 把二叉搜索树转换为累加树

代码:

class Solution {public TreeNode convertBST(TreeNode root) {traverse(root);return root;}int sum = 0;// 右中左遍历,累加节点的值void traverse(TreeNode root) {if (root == null) {return;}traverse(root.right);// 维护累加和sum += root.val;// 将 BST 转化成累加树root.val = sum;traverse(root.left);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/762900.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kotlin中使用ViewBinding绑定控件

kotlin中使用ViewBinding绑定控件 什么是ViewBinding&#xff1f; View Binding是Android Studio 3.6推出的新特性&#xff0c;主要用于减少findViewById的冗余代码&#xff0c;但内部实现还是通过使用findViewById。通过ViewBinding&#xff0c;可以更轻松地编写可与视图交互…

Linux - IO

目录 四种典型IO方式阻塞IO非阻塞IO信号驱动异步IO 多路转接IOselect模型接口 四种典型IO方式 IO&#xff1a;输入输出–过程&#xff1a;等待IO就绪&#xff0c;进行数据拷贝 阻塞&#xff1a;为了完成某功能&#xff0c;发起一个调用&#xff0c;若完成功能条件不具备&#…

String类适合做HashMap的key的原因是什么

在《Java 编程思想》中有这么一句话&#xff1a;设计 hashCode() 时最重要的因素就是对同一个对象调用 hashCode() 都应该产生相同的值。 String 类型的对象对这个条件有着很好的支持&#xff0c;因为 String 对象的 hashCode() 值是根据 String 对象的 内容计算的&#xff…

unity学习(66)——控制器Joystick Pack优化

Joystick Pack这种重力带惯性不利于正常开发。决定进行优化。有一种万事俱备只欠东风的感觉。 源代码如下&#xff1a; 1.在脚本中找到轮盘所输出的方向值 2.把方向的改变值加到鸣人模型身上。 2.1控制器脚本中添加model变量 2.2在unity中赋值 2.3代码中修改位置 using Syst…

C++ [COCI2006-2007#2] ABC

文章目录 一、题目描述[COCI2006-2007#2] ABC题面翻译题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 二、参考代码 一、题目描述 [COCI2006-2007#2] ABC 题面翻译 【题目描述】 三个整数分别为 A , B , C A,B,C A,B,C。这三个数字…

Python:使用 jionlp和cpca 实现国内地址文本解析

目录 使用 jionlp解析国内地址文本使用 cpca 实现解析国内地址文本总结 使用 jionlp解析国内地址文本 jionlp: 中文 NLP 预处理、解析工具包&#xff0c;准确、高效、易用 github: https://github.com/dongrixinyu/JioNLP文档&#xff1a;http://www.jionlp.com/ 使用示例 …

vue2源码学习01配置rollup打包环境

1.下载rollup相关依赖 npm i rollup rollup-plugin-babel babel/core babel/preset-env --save-dev 2.新建rollup.config.js配置打包选项 //rollup可以导出一个对象&#xff0c;作为打包的配置文件 import babel from rollup-plugin-babel export default {input: ./src/ind…

搭建Hadoop集群(完全分布式运行模式)

目录 一、准备模板机(最小化安装)二、配置一台纯净的模板机修改主机名固定IP地址通过yum安装方式安装必要的软件关闭防火墙且禁止自启修改hosts映射文件创建普通用户 并让他能用sudo命令在/opt下创建software和module完成 三、搭建完全分布式运行模式3.1克隆第一台机器hadoop10…

新能源汽车充电桩站点烟火AI识别检测算法应用方案

新能源汽车作为现代科技与环保理念的完美结合&#xff0c;其普及和应用本应带给人们更加便捷和绿色的出行体验。然而&#xff0c;近年来新能源汽车充电火灾事故的频发&#xff0c;无疑给这一领域投下了巨大的阴影。这不禁让人深思&#xff0c;为何这一先进的交通工具在充电过程…

【算法】acwing基础课笔记01-快排,归并

第一章&#xff08;基础算法&#xff09;&#xff08;一&#xff09; 以前排序都没怎么自己手写过&#xff0c;这学期终于决定抛弃各种番和游戏好好学一下…记点笔记激励一下自己。 视频知识 00&#xff1a;0000&#xff1a;30快速排序&#xff0c;00&#xff1a;3000&#…

如何防止Terraform在apply时销毁现有的资源

可以在 Terraform 的生命周期中使用 prevent_destroy 配置来指示 Terraform 不要销毁指定的资源。具体示例如下&#xff1a; 在 provider 的配置中添加 lifecycle_rule&#xff1a; provider "aws" {region "us-west-2"lifecycle_rule {prevent_des…

Vue+SpringBoot在线教育考试及管理平台开发(纯原创)后续还在开发,会持续更新

登录页面设计 登录页面设计思路-分为三个角色进行登录&#xff0c;分别为学生&#xff0c;教师&#xff0c;管理员。 前端将登录设计为表单形式&#xff0c;通过选项组件绑定角色参数&#xff0c;向后端传递角色信息&#xff0c;通过表单绑定向后端传递登录者所有信息 <div …

web蓝桥杯真题:灯的颜色变化

代码及注释&#xff1a; // TODO&#xff1a;完善此函数 显示红色颜色的灯 function red() { //将红色图片元素display显示出来&#xff0c;其他隐藏document.querySelector(#defaultlight).style.display nonedocument.querySelector(#redlight).style.display inline-b…

必示科技携手云杉网络发布“智能可观测性联合解决方案”

近日&#xff0c;必示科技与云杉网络携手发布“智能可观测性联合解决方案”&#xff0c;整体方案融合云杉网络DeepFlow产品在可观测性领域、必示科技AIOps产品在运维数据分析领域的深厚技术积淀&#xff0c;完整实现IT系统高质量、高性能、全栈的可观测数据采集、智能监控和智能…

网络: 数据链路层

数据链路层: 数据帧的封装与传输 以太网数据帧 源地址和目的地址是指网卡的硬件地址(也叫MAC地址), 长度是48位,是在网卡出厂时固化的;帧协议类型字段有三种值,分别对应IP、ARP、RARP;帧末尾是CRC校验码 以太网 "以太网" 不是一种具体的网络, 而是一种技术标准; 既…

String 作为方法参数是值传递还是引用传递

当将一个String作为方法参数传递时&#xff0c;实际上传递的是String对象的引用的副本&#xff0c;而不是String对象本身。即&#xff0c;在方法内部对String对象进行操作时&#xff0c;操作的是引用的副本&#xff0c;而不会影响原始的String对象。这也意味着&#xff0c;如果…

Cubemx串口配置

1.时钟 2.引脚配置 3.重写printf代码 /* USER CODE BEGIN 1 */ int __io_putchar(int ch){HAL_UART_Transmit(&huart1,(uint8_t *) ch, 1,1000);return ch; } /* USER CODE END 1 */

05分布式事务之CAP理论和BASE理论

分布式事务 项目优化 在网站上加载课程详情信息时如果很慢(排除网速)会影响用户的体验性&#xff0c;为了提高响应速度需要将课程详情信息进行缓存并且将课程信息加入索引库方便全局搜索 Redis中的课程缓存信息是将课程发布表中的数据转为json进行存储Elasticsearch中的课程…

Mysql数据库:索引管理

目录 一、索引的概述 1、索引的概念 2、索引的作用 3、索引的副作用 4、创建索引的原则依据 5、索引优化 6、索引的分类 7、数据文件与索引文件 二、管理数据库索引 1、查询索引 2、创建索引 2.1 创建普通索引 2.2 创建唯一索引 2.3 创建主键索引 2.4 创建组合…

58、服务攻防——应用协议设备KibanaZabbix远控向日葵VNCTeamViwer

文章目录 vnc默认端口&#xff1a;5900 or 5902&#xff0c;hydra支持vnc破解。VNC有三种模式&#xff1a;使用vnc密码、windows密码、无密码。 teamviewer、向日葵都是使用之前爆过漏洞进行测试。 zabbix&#xff1a;监控系统&#xff0c;蓝队部署平台。zabbix页面如下&#…