算法训练营day19|654.最大二叉树,617.合并二叉树,700.二叉搜索树中的搜索,98.验证二叉搜索树

1.知识点

2.刷题

654.最大二叉树

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

题目描述:

方法1:递归

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/11/20
 * @Description todo
 */
public class ZuiDaErChaShu654_1 {
    /**
     * 方法1:dfs-递归-前序遍历
     * 1.先找到数组中的最大值,构建为当前节点
     * 2.最大值左边区间构建左子树
     * 3.最大值右边区间构建右子树
     *
     * @param nums
     * @return
     */
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        return dfs(nums, left, right);
    }

    private TreeNode dfs(int[] nums, int left, int right) {
        if (left > right) {
            return null;
        }
        //找到当前区间内最大值的索引,同时也是将这个数组分开的边界
        int bond = findMaxIndex(nums, left, right);

        //构建当前节点
        TreeNode root = new TreeNode(nums[bond]);

        //构建左子树,右子树
        TreeNode leftTreeNode = dfs(nums, left, bond - 1);
        TreeNode rightTreeNode = dfs(nums, bond + 1, right);
        root.left = leftTreeNode;
        root.right = rightTreeNode;

        return root;
    }

    /**
     * 寻找数组中left-right区间内最大值的索引
     *
     * @param nums
     * @param left
     * @param right
     * @return
     */
    private int findMaxIndex(int[] nums, int left, int right) {
        int max = Integer.MIN_VALUE;
        int maxIndex = left;
        for (int i = left; i <= right; i++) {
            if (nums[i] > max) {
                max = nums[i];
                maxIndex = i;
            }
        }
        return maxIndex;
    }

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

方法2:单调栈

package daimasuixiangshuati.day19_erchashu;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Stack;

/**
 * @Author LeiGe
 * @Date 2023/11/20
 * @Description todo
 */
public class ZuiDaErChaShu654_2 {
    /**
     * 方法2:单调栈递减栈:栈顶是最小值
     * 1.方法1中寻找区间内最大值,会将数组中元素多次遍历,时间复杂度O(N^2)
     * 2.通过一个单调递减栈,可以减少多次遍历数组中的元素
     * 3.单调栈操作:插入元素x,栈顶元素y
     * 3.1如果x小于y,则y.right=x,压栈
     * 3.2如果x大于y,则x.left=y,出栈
     * 4.栈底元素为低下根节点
     * 参考:
     * https://leetcode.cn/problems/maximum-binary-tree/solutions/1762400/zhua-wa-mou-si-by-muse-77-myd7/
     *
     * @param nums
     * @return
     */
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        Stack<TreeNode> stack = new Stack<>();
        Deque<TreeNode> deque = new ArrayDeque();
        deque.peek();
        deque.peekLast();
        deque.peekFirst();
        for (int num : nums) {
            //数组值对应的节点
            TreeNode node = new TreeNode(num);
            while (!stack.isEmpty()) {
                TreeNode topNode = stack.peek();
                //当前元素小于栈顶元素,压栈,
                if (topNode.val > node.val) {
                    stack.push(node);
                    topNode.right = node;
                    break;
                } else {//当前元素大于栈顶元素,弹栈
                    stack.pop();
                    node.left = topNode;
                }
            }
            if (stack.isEmpty()) {
                stack.push(node);
            }
        }
        //栈底元素为最终的根节点
        while (stack.size() > 1) {
            stack.pop();
        }
        return stack.peek();
    }

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

617.合并二叉树

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

题目描述:

方法1:递归+构建新树

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/12/3
 * @Description todo
 */
public class ErBingErChaShu617_1 {

    /**
     * 方法1:dfs+递归-构建一个新树-前序遍历
     * 1.二叉树的前序,中序,后序遍历都可以
     *
     * @param root1
     * @param root2
     * @return
     */
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        return dfs1(root1, root2);
    }

    private TreeNode dfs1(TreeNode root1, TreeNode root2) {
        //baseCase
        if (root1 == null && root2 == null) {
            return null;
        }
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }

        //左子树
        TreeNode left = dfs1(root1.left, root2.left);
        //右子树
        TreeNode right = dfs1(root1.right, root2.right);

        //构建新节点
        return new TreeNode(root1.val + root2.val, left, right);
    }

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

方法2:递归+返回其中一个树

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/12/3
 * @Description todo
 */
public class ErBingErChaShu617_2 {
    /**
     * 方法2:dfs+递归-返回其中一个树-前序遍历
     * 1.二叉树的前序,中序,后序遍历都可以
     *
     * @param root1
     * @param root2
     * @return
     */
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        return dfs2(root1, root2);
    }

    private TreeNode dfs2(TreeNode root1, TreeNode root2) {
        //baseCase
        if (root1 == null && root2 == null) {
            return null;
        }
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }

        //左子树
        TreeNode left = dfs2(root1.left, root2.left);
        //右子树
        TreeNode right = dfs2(root1.right, root2.right);

        //返回其中一个树
        root1.val = root1.val + root2.val;
        root1.left = left;
        root1.right = right;
        return root1;
    }

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

方法3:bfs+队列

package daimasuixiangshuati.day19_erchashu;

import java.util.LinkedList;

/**
 * @Author LeiGe
 * @Date 2023/12/3
 * @Description todo
 */
public class ErBingErChaShu617_3 {
    /**
     * 方法3:bfs+队列
     *
     * @param root1
     * @param root2
     * @return
     */
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) {
            return null;
        }
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }


        TreeNode merged = new TreeNode(root1.val + root2.val);
        LinkedList<TreeNode> queue = new LinkedList<>();
        LinkedList<TreeNode> queue1 = new LinkedList<>();
        LinkedList<TreeNode> queue2 = new LinkedList<>();

        queue.addLast(merged);
        queue1.addLast(root1);
        queue2.addLast(root2);

        while (!queue1.isEmpty() && !queue2.isEmpty()) {
            TreeNode node = queue.poll();
            TreeNode node1 = queue1.poll();
            TreeNode node2 = queue2.poll();

            TreeNode left1 = node1.left;
            TreeNode left2 = node2.left;
            TreeNode right1 = node1.right;
            TreeNode right2 = node2.right;

            // 处理两颗树的左子树
            if (left1 != null || left2 != null) {
                // 如果两颗树的左子树都不为空,加入队列
                if (left1 != null && left2 != null) {
                    TreeNode left = new TreeNode(left1.val + left2.val);
                    node.left = left;
                    queue.addLast(left);
                    queue1.addLast(left1);
                    queue2.addLast(left2);
                }
                // 如果一颗树的左子树不为null,直接赋值
                else if (left1 != null) {
                    node.left = left1;
                } else if (left2 != null) {
                    node.left = left2;
                }
            }

            // 相同逻辑处理右子树
            if (right1 != null || right2 != null) {
                if (right1 != null && right2 != null) {
                    TreeNode right = new TreeNode(right1.val + right2.val);
                    node.right = right;
                    queue.addLast(right);
                    queue1.addLast(right1);
                    queue2.addLast(right2);
                } else if (right1 != null) {
                    node.right = right1;
                } else if (right2 != null) {
                    node.right = right2;
                }
            }
        }
        return merged;
    }

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

700.二叉搜索树中的搜索

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

题目描述:

方法1:普通二叉树+dfs

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class ErChaSouSuoShuZhongDeSouSuo700_1 {
    /**
     * 方法1:dfs递归:普通二叉树
     *
     * @param root
     * @param val
     * @return
     */
    public TreeNode searchBST(TreeNode root, int val) {
        return dfs1(root, val);
    }

    private TreeNode dfs1(TreeNode root, int val) {
        //baseCase
        if (root == null || root.val == val) {
            return root;
        }
        TreeNode left = dfs1(root.left, val);
        if (left != null) {
            return left;
        }
        return dfs1(root.right, val);
    }

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

方法2:搜索二叉树+dfs

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class ErChaSouSuoShuZhongDeSouSuo700_2 {
    /**
     * 方法2:dfs递归,利用二叉搜索树特点,优化
     * 1.如果当前节点的值大于要找的val,左子树,否则右子树
     *
     * @param root
     * @param val
     * @return
     */
    public TreeNode searchBST(TreeNode root, int val) {
        return dfs2(root, val);
    }

    private TreeNode dfs2(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        if (val < root.val) {
            return dfs2(root.left, val);
        } else {
            return dfs2(root.right, val);
        }
    }

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

方法3:普通二叉树+迭代

package daimasuixiangshuati.day19_erchashu;

import java.util.Stack;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class ErChaSouSuoShuZhongDeSouSuo700_3 {
    /**
     * 方法3:迭代法
     * 迭代:普通二叉树
     *
     * @param root
     * @param val
     * @return
     */
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        Stack<TreeNode> stack = new Stack<>();
        stack.push(root);
        while (!stack.isEmpty()) {
            TreeNode pop = stack.pop();
            if (pop.val == val) {
                return pop;
            }
            if (pop.right != null) {
                stack.push(pop.right);
            }
            if (pop.left != null) {
                stack.push(pop.left);
            }
        }
        return null;
    }

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

方法4:搜索二叉树+迭代

package daimasuixiangshuati.day19_erchashu;

import java.util.Stack;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class ErChaSouSuoShuZhongDeSouSuo700_4 {
    /**
     * 方法4:迭代法
     * 迭代:利用二叉搜索树特点,优化,可以不需要栈
     *
     * @param root
     * @param val
     * @return
     */
    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;
    }

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

98.验证二叉搜索树

LeetCode链接 98. 验证二叉搜索树 - 力扣(LeetCode)

题目描述:

方法1:中序遍历+prev

package daimasuixiangshuati.day19_erchashu;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class YanZhengErChaSouSuoShu98_1 {
    /**
     * 方法1:中序遍历,如果是搜索二叉树,一定是不降序的
     * 通过一个变量记录前一个子树的值prev
     *
     * @param root
     * @return
     */
    private long prev = Long.MIN_VALUE;

    public boolean isValidBST(TreeNode root) {
        //baseCase
        if (root == null) {
            return true;
        }
        //左子树
        boolean left = isValidBST(root.left);
        if (!left) {
            return false;
        }
        //此节点

        //此节点的值小于左子树节点的值
        if (root.val <= prev) {
            return false;
        }
        prev = root.val;

        //右子树
        boolean right = isValidBST(root.right);

        return right;
    }

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

方法2:中序遍历+数组

package daimasuixiangshuati.day19_erchashu;

import java.util.ArrayList;

/**
 * @Author LeiGe
 * @Date 2023/12/6
 * @Description todo
 */
public class YanZhengErChaSouSuoShu98_2 {
    /**
     * 方法2:中序遍历,如果是搜索二叉树,一定是不降序的
     * 1.将中序遍历的结果加入数组中
     * 2.遍历数组是否是不降序的
     *
     * @param root
     * @return
     */
    public boolean isValidBST(TreeNode root) {
        integers.clear();
        traversal2(root);
        for (int i = 1; i < integers.size(); i++) {
            if (integers.get(i) <= integers.get(i - 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 中序遍历
     *
     * @param root
     */
    ArrayList<Integer> integers = new ArrayList<>();

    private void traversal2(TreeNode root) {
        if (root == null) {
            return;
        }
        traversal2(root.left);
        integers.add(root.val);
        traversal2(root.right);
    }

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

3.小结

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值