leetcode-zgd-day20-654.最大二叉树/617.合并二叉树/700.二叉搜索树中的搜索/98.验证二叉搜索树

46 阅读2分钟

654.最大二叉树

题目链接:654. 最大二叉树 - 力扣(LeetCode)

解题思路:

递归模拟法:按照题目描述进行模拟即可,较好理解

 class Solution {
     public TreeNode constructMaximumBinaryTree(int[] nums) {
         return getNode(nums, 0, nums.length);
     }
     public TreeNode getNode(int[] nums, int begin, int end){ // 注意所有区间左闭右开,循环不变量!
         if(begin >= end) return null;
         // 找到根节点索引
         int curIndex = findMaxIndex(nums, begin, end);
         TreeNode root = new TreeNode(nums[curIndex]);
         root.left = getNode(nums, begin, curIndex);
         root.right = getNode(nums, curIndex + 1, end);
         return root;
     }
     int findMaxIndex(int[] nums, int begin, int end){ // 区间左闭右开
         int ansIndex = begin;
         for(int i = begin; i < end; i++){
             if(nums[i] > nums[ansIndex]) ansIndex = i;
         }
         return ansIndex;
     }
 }

617.合并二叉树

题目链接:617. 合并二叉树 - 力扣(LeetCode)

递归解法:递归解法较好理解

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

迭代解法:借助队列进行迭代合并

需要想清楚的是,队列当中需要存的是什么,最开始想的是队列中可以存空,所有对应的节点都存进去。

但是实际上队列中只需要存入需要合并的节点即可。因为树2中的节点没有了我们根本无需处理,这个分支到此就处理结束了,无需入队。

树1中的节点为空但是树2还有的情况,我们只需要让树1指向树2对应的节点就好了,类似移花接木。至此也就处理完毕了,并不需要入队。

这一点想清楚了这个题也就解好了。

 class Solution {
     public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
         if(root1 == null) return root2;
         if(root2 == null) return root1;
         Queue<TreeNode> que = new LinkedList<>(); // 进入队列的都是需要合并的节点,不需要合并的节点无需插入
         que.offer(root1);
         que.offer(root2);
         while(!que.Empty()){ // 只有两个节点都不为空才会插入队列当中
             TreeNode cur1 = que.poll();
             TreeNode cue2 = que.poll();
             if(cur1.left != null && cur2.left != null){
                 que.offer(cur1.left);
                 que.offer(cue2.left);
             }
             if(cur1.right != null && cur2.right != null){
                 que.offer(cur1.right);
                 que.offer(cue2.right);
             }
             // cur1的左节点为空,直接赋值
             if(cur1.left == null && cur2.left != null){
                 cur1.left = cur2.left;
             }
             // cur1的右节点为空,直接赋值
             if(cur1.right == null && cur2.right != null){
                 cur1.right = cur2.right;
             }
         }
         return root1;
     }
 }

700.二叉搜索树中的搜索

题目链接:700. 二叉搜索树中的搜索 - 力扣(LeetCode)

递归解法:思考子问题是什么,以及结束条件,返回值。

 class Solution {
     public TreeNode searchBST(TreeNode root, int val) { // 该函数是寻找以root为跟的值为val的节点
         if(root == null || root.val == val) return root; // 当前节点判断是不是
         // 一下两条语句只有一条会被执行,所以不会存在覆盖问题。
         TreeNode result = null;
         if(root.val < val) result = searchBST(root.right, val); // 在右子树中,转换成子问题。
         // if(root.val > val) result = searchBST(root.left, val); 用else更好理解
         else result = searchBST(root.left, val); // 在左子树中,转换成子问题
         return result;
     }
 }

迭代解法:迭代就是循环求解啊!循环去找路径就好了

 class Solution {
     public TreeNode searchBST(TreeNode root, int val) {
         while(root != null){
             if(root.val == val) return root;
             else if(root.val > val) root = root.left;
             else root = root.right;
         }
         return null;
     }
 }

98.验证二叉搜索树

题目链接:Loading Question... - 力扣(LeetCode)

解题思路:

递归法:

这个题还是要理解为什么只能用中序遍历,而不能用前序或者是后序。

因为中序遍历数组是单调递增的,对于二叉搜索树而言,所以可以通过判断前面遍历的节点是否比当前节点小来判断二叉树是否符合条件。

 class Solution {
 ​
     TreeNode max;
 ​
     public boolean isValidBST(TreeNode root) {
         // 递归解法
         if(root == null) return true;
         boolean leftIsValid = isValidBST(root.left);
         if(!leftIsValid) return false;
         // 中序遍历,验证二叉树是否符合条件! 利用了二叉搜索树中序遍历数组单调递增的性质。max是root上一个遍历的节点。
         if (max != null && root.val <= max.val) {
             return false;
         }
         max = root;
         boolean rightIsValid = isValidBST(root.right);
         return rightIsValid;
     }
 }

迭代法:

迭代也是中序遍历的迭代而已,只不过在处理中间节点的时候进行了符合该题目的特殊处理。

 class Solution {
     // 迭代
     public boolean isValidBST(TreeNode root) {
         if (root == null) {
             return true;
         }
         Stack<TreeNode> stack = new Stack<>();
         TreeNode pre = null;
         while (root != null || !stack.isEmpty()) {
             while (root != null) {
                 stack.push(root);
                 root = root.left;// 左
             }
             // 中,处理
             TreeNode pop = stack.pop();
             if (pre != null && pop.val <= pre.val) {
                 return false;
             }
             pre = pop;
 ​
             root = pop.right;// 右
         }
         return true;
     }
 }