代码随想录一刷(day20) |654.最大二叉树|617.合并二叉树|700.二叉搜索树中的搜索|98.验证二叉搜索树

654.最大二叉树 leetcode链接

思考

题目要求

  • 二叉树的根是数组中的最大元素。
  • 左子树是通过数组中最大值左边部分构造出的最大二叉树。
  • 右子树是通过数组中最大值右边部分构造出的最大二叉树。

构造树一般采用的是前序遍历,因为先构造中间节点,然后递归构造左子树和右子树。

递归三部曲:

1.明确递归方法的参数和返回类型

public TreeNode constructMaximumBinaryTree(int[] nums)

2.明确递归终止条件

        //终止条件
        if (nums.length == 1) {
            return new TreeNode(nums[0]);
        }

3.明确单层递归逻辑【中序】

        (1)记录到数组中最大值maxValue及其下标maxIndex,并将最大值赋值给root节点的val

        (2)根据题意,以maxIndex为分界点将数组分为左右两部分

        (3)递归计算左边的最大值和右边的最大值

        //中
        int maxValue = 0;
        int maxIndex = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > maxValue) {
                maxValue = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(maxValue);
        //左
        if (maxIndex > 0) {
            int[] temp = new int[maxIndex];
            for (int i = 0; i < maxIndex; i++) {
                temp[i] = nums[i];
            }
            root.left = constructMaximumBinaryTree(temp);
        }
        //右
        if (maxIndex < nums.length - 1) {
            int[] temp = new int[nums.length - maxIndex - 1];
            int j = 0;
            for (int i = maxIndex + 1; i < nums.length; i++,j++) {
                temp[j] = nums[i];
            }
            root.right = constructMaximumBinaryTree(temp);
        }
        return root;

代码展示

class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        //终止条件
        if (nums.length == 1) {
            return new TreeNode(nums[0]);
        }

        //中
        int maxValue = 0;
        int maxIndex = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] > maxValue) {
                maxValue = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(maxValue);
        //左
        if (maxIndex > 0) {
            int[] temp = new int[maxIndex];
            for (int i = 0; i < maxIndex; i++) {
                temp[i] = nums[i];
            }
            root.left = constructMaximumBinaryTree(temp);
        }
        //右
        if (maxIndex < nums.length - 1) {
            int[] temp = new int[nums.length - maxIndex - 1];
            int j = 0;
            for (int i = maxIndex + 1; i < nums.length; i++,j++) {
                temp[j] = nums[i];
            }
            root.right = constructMaximumBinaryTree(temp);
        }
        return root;
    }
}
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

总结

关键是理解题意,如题中给出的最大二叉树的定义

优化:可以通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。

617.合并二叉树

思考

合并二叉树要考虑,相同位置的节点是否为空,如果为空就返回另一个节点的值赋值(这可以解决两个节点都为空和只有一个节点为空的情况),如果都不为空则返回二者之和。这里选择创建一个新的二叉树返回,不改变原来的二叉树

递归三部曲:

1.明确递归方法的参数和返回值

public TreeNode mergeTrees(TreeNode root1, TreeNode root2)

2.明确递归方法的终止条件

if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1;
        }

3.明确单层递归逻辑

        //中
        TreeNode root = new TreeNode();
        root.val = root1.val + root2.val;

        //左
        root.left = mergeTrees(root1.left,root2.left);
        //右
        root.right = mergeTrees(root1.right,root2.right);

        return root;

代码展示

class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        if (root1 == null) {
            return root2;
        }
        if (root2 == null) {
            return root1; 
        }
        //中
        TreeNode root = new TreeNode();
        root.val = root1.val + root2.val;
        
        //左
        root.left = mergeTrees(root1.left,root2.left);
        //右
        root.right = mergeTrees(root1.right,root2.right);

        return root;
    }
}
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

总结

依然是创建二叉树的逻辑,不过在二叉树节点的值上有所不同

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

思考

二叉搜索树的搜索相对于普通二叉树搜索更加方便,代码逻辑基本相同。不过在原来普通二叉树的搜索中向左或向右搜索时添加了判断条件,减少了搜索的路径。

递归三部曲

1.明确递归方法的参数和返回值

public TreeNode searchBST(TreeNode root, int val)

2.明确递归方法的终止条件

  if (root == null || root.val == val) {
            return root;
        }

3.明确单层递归逻辑

TreeNode result = null;
        if (root.val < val) {   //注意这里的条件
            result = searchBST(root.right,val); //注意这里的逻辑 传入的是root.right 而不是root.left
        }
        if (root.val > val) {
            result = searchBST(root.left,val);
        }
        return result;

代码展示

递归法

class Solution {
  public TreeNode searchBST(TreeNode root, int 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);
        }
        return result;
    }
}
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }

迭代法

本题使用 迭代法的代码也非常简洁明了

    //迭代法
    public TreeNode searchBST(TreeNode root, int val) {
        while (root != null) {
            if (val > root.val) {
                root = root.right;
            } else if (val < root.val) {
                root = root.left;
            }else {
                return root;
            }
        }
        return null;
    }

总结

一提到二叉树遍历的迭代法,可能立刻想起使用栈来模拟深度遍历,使用队列来模拟广度遍历。

对于二叉搜索树可就不一样了,因为二叉搜索树的特殊性,也就是节点的有序性,可以不使用辅助栈或者队列就可以写出迭代法。

对于一般二叉树,递归过程中还有回溯的过程,例如走一个左方向的分支走到头了,那么要调头,在走右分支。

对于二叉搜索树,不需要回溯的过程,因为节点的有序性就帮我们确定了搜索的方向。

                                                                                                         ————《代码随想录》

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

思考

验证二叉树是否为二叉搜索树,即判断在中序遍历时前一个结点的值是否小于当前节点。可以使用暴力解法,将中序遍历的结果放到数组中,最后再判断数组是否单调递增。除此之外,也可以使用一个指针指向前节点,每遍历一个节点时做一次比较,具体逻辑看代码展示。

递归三部曲:

1.明确递归方法的参数和返回值

public boolean isValidBST(TreeNode root)

2.明确递归方法终止条件

if (root == null) {
            return true;
        }

3.明确单层递归逻辑

         //左
        boolean left = isValidBST(root.left);
            if (preNode != null && preNode.val >= root.val) {
            return false;
         }
        preNode = root;
        //右           
        boolean right = isValidBST(root.right);

        return right && left;

代码展示

class Solution {
     private long minValue = Long.MIN_VALUE;
    public boolean isValidBST(TreeNode root) {
        if (root == null) {
            return true;
        }

        boolean left = isValidBST(root.left);
        if (minValue >= root.val) {
            return false;
        }
        minValue = root.val;
        boolean right = isValidBST(root.right);

        return right && left;
    }
}
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    public TreeNode() {
    }

    public TreeNode(int val) {
        this.val = val;
    }

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

总结

使用前置指针的方式比使用数组的方式和设置最小值的方法方便

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值