当前位置:   article > 正文

leetCode - - - 二叉树

leetCode - - - 二叉树

目录​​​​​​​

1.前中后序遍历(递归)

2.前中后序遍历(迭代)

3.翻转二叉树(LeetCode 226)

4.最大二叉树( LeetCode 654 )

5.平衡二叉树( LeetCode 110 )

6.二叉树的最小深度( LeetCode 111 )

7.二叉树的最大深度( LeetCode 104 )

8.二叉树的最近公共祖先( LeetCode 236 )(重点)

9.从前序与中序遍历序列构造二叉树( LeetCode 105 )(重点)

10.从中序与后序遍历序列构造二叉树( LeetCode 106 )

11.合并二叉树(LeetCode 617)

12.验证二叉搜索树(LeedCode 98)


1.前中后序遍历(递归)

前序

https://leetcode.cn/problems/binary-tree-preorder-traversal/

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. public List<Integer> preorderTraversal(TreeNode root) {
  18. List<Integer> list=new ArrayList<>();
  19. preorder(root,list);
  20. return list;
  21. }
  22. private void preorder(TreeNode root,List<Integer>list){
  23. if(root==null){
  24. return;
  25. }
  26. list.add(root.val);
  27. preorder(root.left,list);
  28. preorder(root.right,list);
  29. }
  30. }

中序

 https://leetcode.cn/problems/binary-tree-inorder-traversal/

  1. class Solution {
  2. public List<Integer> inorderTraversal(TreeNode root) {
  3. List<Integer> list=new ArrayList();
  4. inorder(root,list);
  5. return list;
  6. }
  7. private void inorder(TreeNode root,List<Integer> list){
  8. if(root==null){
  9. return;
  10. }
  11. inorder(root.left,list);
  12. list.add(root.val);
  13. inorder(root.right,list);
  14. }
  15. }

后序

https://leetcode.cn/problems/binary-tree-postorder-traversal/

  1. class Solution {
  2. public List<Integer> postorderTraversal(TreeNode root) {
  3. List<Integer> list=new ArrayList();
  4. postorder(root,list);
  5. return list;
  6. }
  7. private void postorder(TreeNode root,List<Integer> list){
  8. if(root==null){
  9. return;
  10. }
  11. postorder(root.left,list);
  12. postorder(root.right,list);
  13. list.add(root.val);
  14. }
  15. }

2.前中后序遍历(迭代)

先整体写出遍历的顺序,然后再根据前中后序的顺序,确定添加到List的时机。三种遍历统一可以使用一个模版

  1. class Solution {
  2. public List<Integer> preorderTraversal(TreeNode root) {
  3. // 设置一个数组用来保存二叉树前序遍历的结果
  4. List<Integer> preorderResult=new ArrayList<>();
  5. // 设置一个数组用来保存二叉树中序遍历的结果
  6. //List<Integer> inorderResult = new ArrayList<>();
  7. // 设置一个数组用来保存二叉树后序遍历的结果
  8. //List<Integer> postorderResult = new ArrayList<>();
  9. // 设置一个栈,用来保存路径
  10. Stack<TreeNode> stack=new Stack<>();
  11. // 左代表该节点的左右孩子节点都没有遍历
  12. int nodeLeft=1;
  13. // 右代表该节点的左孩子节点已经遍历,右孩子节点还没有遍历
  14. int nodeRight=2;
  15. // 上代表左右孩子节点都已经遍历,需要返回到它的父节点
  16. int nodeUp=3;
  17. // 每个节点的初始化状态都是从左开始
  18. int nodeState=nodeLeft;
  19. TreeNode node=root;
  20. while(node!=null){
  21. if(nodeState==nodeLeft){
  22. preorderResult.add(node.val);
  23. if(node.left!=null){
  24. stack.push(node);
  25. node=node.left;
  26. }else{
  27. nodeState=nodeRight;
  28. }
  29. }else if(nodeState==nodeRight){
  30. // 把当前节点加入到二叉树中序遍历的结果数组中
  31. // inorderResult.add(node.val);
  32. if(node.right!=null){
  33. stack.push(node);
  34. node=node.right;
  35. nodeState=nodeLeft;
  36. }else{
  37. nodeState=nodeUp;
  38. }
  39. }else if(nodeState==nodeUp){
  40. // 把当前节点加入到二叉树后序遍历的结果数组中
  41. //postorderResult.add(node.val);
  42. TreeNode parent=null;
  43. if(!stack.isEmpty()){
  44. parent=stack.pop();
  45. if(parent.left==node){
  46. nodeState=nodeRight;
  47. }
  48. }
  49. node=parent;
  50. }
  51. }
  52. return preorderResult;
  53. }
  54. }

3.翻转二叉树(LeetCode 226)

https://leetcode.cn/problems/invert-binary-tree/description/

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

示例 1:

输入:root = [4,2,7,1,3,6,9]
输出:[4,7,2,9,6,3,1]

  1. class Solution {
  2. public TreeNode invertTree(TreeNode root) {
  3. if(root==null){
  4. return null;
  5. }
  6. if(root.left==null && root.right==null){
  7. return root;
  8. }
  9. TreeNode left=invertTree(root.left);
  10. TreeNode right=invertTree(root.right);
  11. root.left=right;
  12. root.right=left;
  13. return root;
  14. }
  15. }

  1. class Solution {
  2. public TreeNode invertTree(TreeNode root) {
  3. // 1、递归终止条件一,当前节点为空的时候,就返回 null
  4. if(root == null) return null;
  5. // 2、递归终止条件二,当前节点为叶子节点的时候,就返回这个节点
  6. if( root.left == null && root.right == null){
  7. // 返回这个节点
  8. return root;
  9. }
  10. // 3、把当前这个节点 root 的左子树进行翻转操作
  11. TreeNode left = invertTree(root.left);
  12. // 4、把当前这个节点 root 的右子树进行翻转操作
  13. TreeNode right = invertTree(root.right);
  14. // 5、把翻转成功的右子树赋值给 root 的左子树
  15. root.left = right;
  16. // 6、把翻转成功的左子树赋值给 root 的右子树
  17. root.right = left;
  18. // 7、返回翻转成功的二叉树的根节点
  19. return root;
  20. }
  21. }

4.最大二叉树( LeetCode 654 )

https://leetcode.cn/problems/maximum-binary-tree/description/

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

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

返回 nums 构建的 最大二叉树 

  1. class Solution {
  2. public TreeNode constructMaximumBinaryTree(int[] nums) {
  3. return maxBinaryTreeNode(nums,0,nums.length-1);
  4. }
  5. private TreeNode maxBinaryTreeNode(int[]nums,int left,int right){
  6. if(left>right){
  7. return null;
  8. }
  9. if(left==right){
  10. return new TreeNode(nums[left]);
  11. }
  12. int maxIndex=left;
  13. for(int i=left+1;i<right+1;i++){
  14. if(nums[i]>nums[maxIndex]){
  15. maxIndex=i;
  16. }
  17. }
  18. TreeNode root=new TreeNode(nums[maxIndex]);
  19. TreeNode leftNode=maxBinaryTreeNode(nums,left,maxIndex-1);
  20. TreeNode rightNode=maxBinaryTreeNode(nums,maxIndex+1,right);
  21. root.left=leftNode;
  22. root.right=rightNode;
  23. return root;
  24. }
  25. }

5.平衡二叉树( LeetCode 110 )

https://leetcode.cn/problems/balanced-binary-tree/

给定一个二叉树,判断它是否是 

平衡二叉树:每个节点 的左右两个子树的高度差的绝对值不超过 1 。

示例 1:

输入:root = [3,9,20,null,null,15,7]
输出:true

示例 2:

输入:root = [1,2,2,3,3,null,null,4,4]
输出:false

  1. class Solution {
  2. public boolean isBalanced(TreeNode root) {
  3. return recur(root)!=-1;
  4. }
  5. private int recur(TreeNode curNode){
  6. if(curNode==null){
  7. return 0;
  8. }
  9. int left=recur(curNode.left);
  10. if(left==-1) return -1;
  11. int right=recur(curNode.right);
  12. if(right==-1) return -1;
  13. return Math.abs(left-right)<2 ? Math.max(left,right)+1:-1;
  14. }
  15. }
  1. class Solution {
  2. public boolean isBalanced(TreeNode root) {
  3. // 自底向上判断,只要返现有叶子树出现非平衡二叉树的情况,那么就是不是平衡二叉树了
  4. return recur(root) != -1;
  5. }
  6. private int recur(TreeNode curNode) {
  7. // 递归终止条件
  8. // 如果当前节点 curNode 为空,那么高度就是 0
  9. if (curNode == null) return 0;
  10. // 递归的计算当前节点 curNode 的左子树高度
  11. int left = recur(curNode.left);
  12. // 如果发现为 -1,即表示左子树中出现了高度差大于 2 的情况,已经不是平衡二叉树了,可以直接返回这个结果给上层
  13. // 提前终止了后续的判断
  14. if(left == -1) return -1;
  15. // 递归的计算当前节点 curNode 的右子树高度
  16. int right = recur(curNode.right);
  17. // 如果发现为 -1,即表示右子树中出现了高度差大于 2 的情况,已经不是平衡二叉树了,可以直接返回这个结果给上层
  18. // 提前终止了后续的判断
  19. if(right == -1) return -1;
  20. // 1、否则说明在 curNode 的左子树中没有发现不是平衡二叉树的情况
  21. // 2、否则说明在 curNode 的右子树中没有发现不是平衡二叉树的情况
  22. // 因此计算一下当前节点 curNode 是否是平衡二叉树
  23. // 即计算 curNode 的左子树高度与右子树高度差
  24. // 如果发现小于 2,那么返回以当前节点 curNode 为根节点的子树的最大高度
  25. // 即节点 curNode 的左右子树中最大高度加 1
  26. return Math.abs(left - right) < 2 ? Math.max(left, right) + 1 : -1;
  27. }
  28. }

6.二叉树的最小深度( LeetCode 111 )

即为求最短路径

https://leetcode.cn/problems/minimum-depth-of-binary-tree/

  1. class Solution {
  2. public int minDepth(TreeNode root) {
  3. Queue<TreeNode> nodeTree=new LinkedList<>();
  4. if(root==null){
  5. return 0;
  6. }
  7. nodeTree.add(root);
  8. int depth=0;
  9. while(nodeTree!=null){
  10. int size=nodeTree.size();
  11. depth++;
  12. for(int i=0;i<size;i++){
  13. TreeNode node=nodeTree.poll();
  14. if(node.left==null && node.right==null){
  15. return depth;
  16. }
  17. if(node.left!=null){
  18. nodeTree.add(node.left);
  19. }
  20. if(node.right!=null){
  21. nodeTree.add(node.right);
  22. }
  23. }
  24. }
  25. return depth;
  26. }
  27. }

来一个趴菜现在才知道的知识点。。。虽然此题判断条件中queue != null 和 !queue.isEmpty() 都不会报错。。。

!queue.isEmpty()更准确,queue != null不报错是因为上面有添加root,对queue已经有初始化了。

queue != null 和 !queue.isEmpty() 是两个用于不同目的的检查,它们在代码中的使用情况和意图有所不同。
queue != null 是用来确认队列对象是否已经初始化。它主要用于确保代码在访问队列之前不会引发 NullPointerException。
!queue.isEmpty() 是用来检查队列是否有元素。在尝试访问或操作队列的元素之前进行检查,以确保队列中有数据可以处理。
通常,这两个检查是相辅相成的。在处理队列时,首先需要确认队列对象本身是有效的 (queue != null),然后检查队列是否包含元素 (!queue.isEmpty())。

  1. class Solution {
  2. public int minDepth(TreeNode root) {
  3. // 边界情况处理
  4. if (root == null) return 0;
  5. // 设置一个队列,用来存储二叉树中的元素
  6. Queue<TreeNode> nodeQueue = new LinkedList<>();
  7. // 队列添加二叉树的根节点
  8. nodeQueue.add(root);
  9. // 设置 depth 用来保存输出结果
  10. int depth = 0;
  11. // 遍历队列,直到队列为空,说明访问了二叉树中所有的节点
  12. while (!nodeQueue.isEmpty()) {
  13. // 用来记录 queue 的长度,即每层节点的个数
  14. int size = nodeQueue.size();
  15. // 每到一层,深度就 +1
  16. depth++;
  17. // 使用 for 循环,将 nodeQueue 中的元素统计
  18. for (int i = 0; i < size; i++) {
  19. // 从 queue 中取出一个节点,此时,nodeQueue 已经抛出了这个节点
  20. TreeNode curNode = nodeQueue.poll();
  21. // curNode.left == null && curNode.right == null
  22. // 说明是叶子结点
  23. // 由于【最小深度是从根节点到最近叶子节点的最短路径上的节点数量】
  24. // 直接返回 depth
  25. if(curNode.left == null && curNode.right == null){
  26. return depth;
  27. }
  28. // 判断当前节点的左子节点是否有值,如果有,则添加到 nodeQueue 中
  29. if (curNode.left != null){
  30. nodeQueue.add(curNode.left);
  31. }
  32. // 判断当前节点的右子节点是否有值,如果有,则添加到 nodeQueue 中
  33. if (curNode.right != null){
  34. nodeQueue.add(curNode.right);
  35. }
  36. }
  37. }
  38. // 返回 depth
  39. return depth;
  40. }
  41. }

7.二叉树的最大深度( LeetCode 104 )

https://leetcode.cn/problems/maximum-depth-of-binary-tree/description/

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

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

  1. class Solution {
  2. public int maxDepth(TreeNode root) {
  3. // 如果 root 为空,直接返回 0
  4. if(root == null) return 0;
  5. // 递归调用 maxDepth,求出当前节点的左子树的最大深度
  6. int left = maxDepth(root.left);
  7. // 递归调用 maxDepth,求出当前节点的右子树的最大深度
  8. int right = maxDepth(root.right);
  9. // 求出当前节点的左右子树中较大的值
  10. int childMaxDepth = Math.max(left,right);
  11. // 二叉树的最大深度就是它的左右子树中较大的值加上 1
  12. return childMaxDepth + 1;
  13. }
  14. }

8.二叉树的最近公共祖先( LeetCode 236 )(重点)

https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/

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

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

  1. class Solution {
  2. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
  3. if(root==null) return null;
  4. if(root==p) return p;
  5. if(root==q) return q;
  6. TreeNode left=lowestCommonAncestor(root.left,p,q);
  7. TreeNode right=lowestCommonAncestor(root.right,p,q);
  8. if(left==null && right==null){
  9. return null;
  10. }else if(left==null){
  11. return right;
  12. }else if(right==null){
  13. return left;
  14. }else{
  15. return root;
  16. }
  17. }
  18. }
  1. class Solution {
  2. public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
  3. // 1、如果此时访问的节点 root 为 null,那么直接返回 null
  4. if(root == null ) return null;
  5. // 2、如果此时访问的节点 root 为指定节点 p,那么返回 p 这个节点
  6. if(root == p) return p;
  7. // 3、如果此时访问的节点 root 为指定节点 q,那么返回 q 这个节点
  8. if(root == q) return q;
  9. // 4、经过上面 1、2、3 的判断之后,root 这个节点必然不是 p、q、null 这三种情况的节点
  10. // 接下来,去递归的判断当前节点 root 的左右子树是否包含 p 、q 这两个指定节点
  11. // 5、递归的去查找 root 的左子树,判断是否包含p 、q 这两个指定节点
  12. // 如果 root 的左子树节点和它的左子树所有节点中包含 p,那么 left 的值就是 p
  13. // 如果 root 的左子树节点和它的左子树所有节点中包含 q,那么 left 的值就是 q
  14. // 如果 root 的左子树节点和它的左子树所有节点中既不包含 p,也不包含 q,那么 left 的值就是 null
  15. TreeNode left = lowestCommonAncestor(root.left, p, q);
  16. // 6、递归的去查找 root 的右子树,判断是否包含p 、q 这两个指定节点
  17. // 如果 root 的右子树节点和它的右子树所有节点中包含 p,那么 right 的值就是 p
  18. // 如果 root 的右子树节点和它的右子树所有节点中包含 q,那么 right 的值就是 q
  19. // 如果 root 的右子树节点和它的右子树所有节点中既不包含 p,也不包含 q,那么 right 的值就是 null
  20. TreeNode right = lowestCommonAncestor(root.right, p, q);
  21. // 7、判断完当前节点 root 、 root 的左子树 left、root 的右子树 right 的情况后
  22. // 开始向父节点传递信息
  23. // 8、如果 root 节点的左子树 left 和右子树 right 都没有找到指定节点 p、q
  24. // 并且 root 自己本身也不是指定节点 p、q
  25. // 那么它给父节点传递的信息就是以 root 为根节点的那颗二叉树没有指定节点 p、q
  26. if(left == null && right == null){
  27. // 返回 null,告诉 root 的父节点,这里没找到指定节点 p、q
  28. return null;
  29. // 9、如果在 root 节点的左子树 left 中没有找到指定节点 p、q
  30. // 那么以 root 为根节点的那颗二叉树能不能找到指定节点 p、q 完全取决于 right 了
  31. }else if(left == null){
  32. // 返回 right ,告诉 root 的父节点,能不能找到指定节点 p、q 完全取决于 right
  33. return right;
  34. // 10、如果在 root 节点的右子树 right 中没有找到指定节点 p、q
  35. // 那么以 root 为根节点的那颗二叉树能不能找到指定节点 p、q 完全取决于 left 了
  36. }else if(right == null){
  37. // 返回 left ,告诉 root 的父节点,能不能找到指定节点 p、q 完全取决于 left
  38. return left;
  39. // 11、此时,left != null 并且 right != null
  40. // 这说明在以 root 节点为根节点的那棵二叉树中找到了指定节点 p ,也找到了指定节点 q
  41. // 那么就告诉父节点,root 就是 p、q 的最近公共祖先
  42. }else{
  43. // 返回 root ,告诉 root 的父节点,root 就是 p、q 的最近公共祖先
  44. return root;
  45. }
  46. }
  47. }

9.从前序与中序遍历序列构造二叉树( LeetCode 105 )(重点)

https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

  1. class Solution {
  2. public TreeNode buildTree(int[] preorder, int[] inorder) {
  3. HashMap<Integer,Integer> map=new HashMap<>();
  4. for(int i=0;i<inorder.length;i++){
  5. map.put(inorder[i],i);
  6. }
  7. TreeNode root=new TreeNode(preorder[0]);
  8. for(int i=1;i<preorder.length;i++){
  9. TreeNode node=new TreeNode(preorder[i]);
  10. insert(root,node,map);
  11. }
  12. return root;
  13. }
  14. private void insert(TreeNode root,TreeNode node,HashMap<Integer,Integer> map){
  15. while(node!=root){
  16. if(map.get(node.val)<map.get(root.val)){
  17. if(root.left==null){
  18. root.left=node;
  19. }
  20. root=root.left;
  21. }else{
  22. if(root.right==null){
  23. root.right=node;
  24. }
  25. root=root.right;
  26. }
  27. }
  28. }
  29. }
  1. class Solution {
  2. public TreeNode buildTree(int[] preorder, int[] inorder) {
  3. // 题目中说 preorder 和 inorder 均无重复元素
  4. // 通过哈希表把中序遍历序列中的值和顺序建立映射关系
  5. HashMap<Integer, Integer> map = new HashMap<>();
  6. // 通过 for 循环,遍历完中序遍历序列中的所有元素
  7. for (int i = 0; i < inorder.length; i++) {
  8. // 以中序序列中的元素值 inorder[i] 作为 key
  9. // 以位置 i 作为 value
  10. // 存放到哈希表中
  11. // 比如中序遍历序列中的元素是 [ A , D , E , F , G , H , M , Z ]
  12. // 那么这个哈希表就是以下的样子
  13. // | 索引 | 位置 |
  14. // | A | 0 |
  15. // | D | 1 |
  16. // | E | 2 |
  17. // | F | 3 |
  18. // | G | 4 |
  19. // | H | 5 |
  20. // | M | 6 |
  21. // | Z | 7 |
  22. map.put(inorder[i], i);
  23. }
  24. // 下面开始构建二叉树
  25. // 把前序遍历序列中的第一个元素 preorder[0] 作为二叉树的根节点
  26. // 因为任意二叉树的前序遍历序列中的第一个元素,一定是二叉树的根节点
  27. TreeNode root = new TreeNode(preorder[0]);
  28. // 继续遍历前序遍历序列中的其它元素
  29. for(int i = 1 ; i < preorder.length ; i++){
  30. // 把当前遍历的元素构造为一个二叉树的节点
  31. TreeNode node = new TreeNode(preorder[i]);
  32. // 把构造的节点插入到以 root 为根节点的二叉树中
  33. insertNode(root,node,map);
  34. }
  35. // 当 preorder 中所有元素都构造并且插入完毕之后
  36. // 二叉树就完成了构建
  37. return root;
  38. }
  39. // root : 二叉树的根节点
  40. // node : 待插入的节点
  41. // map : 节点值和中序遍历序列位置的映射
  42. private void insertNode(TreeNode root,TreeNode node,HashMap<Integer,Integer> map){
  43. // 当 root 和 node 指向的节点相同时,跳出循环
  44. while(root != node){
  45. // 如果 node 的中序遍历序列位置小于 root 的中序遍历序列位置
  46. // 说明 node 应该在 root 的左子树中
  47. if(map.get(node.val) < map.get(root.val)){
  48. // 如果此时 root 没有左子树
  49. if(root.left == null){
  50. // 那么就把 node 设置为 root 的左子树
  51. root.left = node;
  52. }
  53. // 1、如果之前 root 没有左子树,那么通过上面的代码,就设置好了 root 的左子树
  54. // 也就是说 node 是 root 的一个叶子节点,完成了插入操作
  55. // 把 root 指向 root.left 后,root 为 node,跳出了循环
  56. // 2、如果之前 root 已经有左子树,那么就不能直接把 node 插入到 root 的左子树上
  57. // 需要判断应该把 node 插入到 root 左子树上的孩子节点的那个位置上
  58. // 比如现在的 root 是这个样子,node 为 A
  59. // G
  60. // /
  61. // D
  62. // / \
  63. // ① ②
  64. // root 已经有左子树 D 了,所以 node 应该考虑插入到 D 中的 ① 还是 ② 上面
  65. // 所以,把 root 指向 root.left ,继续遍历 root 的左子树的情况
  66. root = root.left;
  67. }else{
  68. // 如果 node 的中序遍历序列位置大于 root 的中序遍历序列位置
  69. // 说明 node 应该在 root 的右子树中
  70. // 如果此时 root 没有右子树
  71. if(root.right == null){
  72. // 那么就把 node 设置为 root 的右子树
  73. root.right = node;
  74. }
  75. // 把 root 指向 root.right ,继续遍历 root 的右子树的情况
  76. root = root.right;
  77. }
  78. }
  79. }
  80. }

10.从中序与后序遍历序列构造二叉树( LeetCode 106 )

https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/

与上面前中构造基本一致,不同的是后序数组从后往前遍历,后序数组的最后一个值,为整棵树的根节点。

  1. class Solution {
  2. public TreeNode buildTree(int[] inorder, int[] postorder) {
  3. HashMap<Integer,Integer> map=new HashMap<>();
  4. for(int i=0;i<inorder.length;i++){
  5. map.put(inorder[i],i);
  6. }
  7. TreeNode root=new TreeNode(postorder[postorder.length-1]);
  8. for(int i=postorder.length-2;i>=0;i--){
  9. TreeNode node=new TreeNode(postorder[i]);
  10. insert(root,node,map);
  11. }
  12. return root;
  13. }
  14. private void insert(TreeNode root,TreeNode node,HashMap<Integer,Integer> map){
  15. while(node!=root){
  16. if(map.get(node.val)<map.get(root.val)){
  17. if(root.left==null){
  18. root.left=node;
  19. }
  20. root=root.left;
  21. }else{
  22. if(root.right==null){
  23. root.right=node;
  24. }
  25. root=root.right;
  26. }
  27. }
  28. }
  29. }

11.合并二叉树(LeetCode 617)

https://leetcode.cn/problems/merge-two-binary-trees/description/​​​​​​​

给你两棵二叉树: root1 和 root2 。

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

返回合并后的二叉树。

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

  1. class Solution {
  2. public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
  3. if(root1==null && root2==null){
  4. return null;
  5. }
  6. if(root1==null){
  7. return root2;
  8. }
  9. if(root2==null){
  10. return root1;
  11. }
  12. TreeNode mergeNode=new TreeNode(root1.val+root2.val);
  13. mergeNode.left=mergeTrees(root1.left,root2.left);
  14. mergeNode.right=mergeTrees(root1.right,root2.right);
  15. return mergeNode;
  16. }
  17. }

12.验证二叉搜索树(LeedCode 98)

https://leetcode.cn/problems/validate-binary-search-tree/

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

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

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

解法一:中序遍历+比较数组是否单调递增 

  1. //二叉搜索树的中序遍历,节点的值一定是单调递增的
  2. //将二叉搜索树的中序遍历的值存放在数组中
  3. //判断这个数组是否是单调递增的
  4. class Solution {
  5. public boolean isValidBST(TreeNode root) {
  6. List<Integer> list=new ArrayList<>();
  7. inorderTree(root,list);
  8. return isCreasing(list);
  9. }
  10. private void inorderTree(TreeNode root,List<Integer> list){
  11. if(root==null){
  12. return;
  13. }
  14. inorderTree(root.left,list);
  15. list.add(root.val);
  16. inorderTree(root.right,list);
  17. }
  18. private boolean isCreasing(List<Integer> list){
  19. for(int i=1;i<list.size();i++){
  20. if(list.get(i)<=list.get(i-1)){
  21. return false;
  22. }
  23. }
  24. return true;
  25. }
  26. }

解法二:中序遍历+双指针

相比上种方法,少了一步存放各个节点的值。在中序遍历的过程中,每次比较当前应该节点和当前节点的大小即可。

  1. class Solution {
  2. public boolean isValidBST(TreeNode root) {
  3. return inorderTree(root);
  4. }
  5. //如果当前节点为空,则返回 true。这是递归的终止条件,也表明空节点是有效的 BST。
  6. TreeNode pre=null;
  7. private boolean inorderTree(TreeNode root){
  8. if(root==null){
  9. return true;
  10. }
  11. //首先递归遍历当前节点的左子树。如果左子树不符合 BST 的条件(返回 false),则当前树也不符合 BST 的条件,返回 false。
  12. if(!inorderTree(root.left)){
  13. return false;
  14. }
  15. //prev != null:确保 prev 已经被初始化,检查当前节点值 node.val 是否大于前一个节点的值prev.val
  16. if(pre!=null && root.val<=pre.val){
  17. return false;
  18. }
  19. //更新 prev 为当前节点,以便在接下来的遍历中进行比较
  20. pre=root;
  21. //遍历当前节点的右子树。如果右子树不符合 BST 的条件(返回 false),则返回 false;否则,返回 true
  22. return inorderTree(root.right);
  23. }
  24. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/1021272
推荐阅读
相关标签
  

闽ICP备14008679号