代码随想录Day22

654.最大二叉树

题目:代码随想录 (programmercarl.com)

思路:先找到最大值,然后以最大值为分割点,左边的是左子树,右边的是右子树,可以模仿通过后序、中序序列构造

递归三步曲

1、参数,数组,左子树起始、左子树终止、右子树起始、右子树终止,返回root

2、终止条件,根据左右子树的起始终止位置指针来判断

3、递归逻辑,要更新左右子树,起始、终止位置的指针

我想了另外一个思路,每次遍历,传递根节点和左右子树数组进去,还是太麻烦了,我放弃

尝试
class Solution {
    Map<Integer,Integer> map;
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        map = new HashMap<>();
        int maxNode = Integer.MIN_VALUE;
        int rootIndex = 0;
        for(int i = 0; i < nums.length; i++){
            map.put(nums[i],i);
            if(nums[i]>maxNode){
                 maxNode = nums[i];
                 rootIndex = i;
            }
        }
        int[] leftTree = new int[rootIndex];
        int[] rightTree = new int[nums.length - rootIndex];
        for(int i = 0; i < nums.length; i++){
            if(i > rootIndex) rightTree[i] = nums[i];
            leftTree[i] = nums[i];
        }
        return getNode(nums[rootIndex],leftTree,rightTree);
        
    }
    public TreeNode getNode(TreeNode root,int[] leftTree,int[] rightTree){
        TreeNode root = new TreeNode(nums[rootIndex]);
        root.left = getNode();
        root.right = getNode();
        return root;
    }
}

// 默写
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return getNode(nums,0,nums.length - 1);
    }
    public TreeNode getNode(int[] nums,int begin,int end){
        if(begin > end) return null;
        if(begin - end == 1) return new TreeNode(nums[begin]);
        int maxIndex = begin;
        int maxValue = nums[begin];
        for(int i = begin; i < end ; i ++){
            if(nums[i] > maxValue){
                maxValue = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(nums[maxIndex]);
        root.left = getNode(nums, begin, maxIndex -1);
        root.right = getNode(nums, maxIndex + 1,end);
        return root;
    }
}
答案
class Solution {
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        return constructMaximumBinaryTree1(nums, 0, nums.length);
    }

    public TreeNode constructMaximumBinaryTree1(int[] nums, int leftIndex, int rightIndex) {
        if (rightIndex - leftIndex < 1) {// 没有元素了
            return null;
        }
        if (rightIndex - leftIndex == 1) {// 只有一个元素
            return new TreeNode(nums[leftIndex]);
        }
        int maxIndex = leftIndex;// 最大值所在位置
        int maxVal = nums[maxIndex];// 最大值
        for (int i = leftIndex + 1; i < rightIndex; i++) {
            if (nums[i] > maxVal){
                maxVal = nums[i];
                maxIndex = i;
            }
        }
        TreeNode root = new TreeNode(maxVal);
        // 根据maxIndex划分左右子树
        root.left = constructMaximumBinaryTree1(nums, leftIndex, maxIndex);
        root.right = constructMaximumBinaryTree1(nums, maxIndex + 1, rightIndex);
        return root;
    }
}
小结

🍉每次递归肯定都要找一次最大值,最大值传递给左右孩子去递归

🍉剪枝操作,【righIndex - leftIndex < 1】时返回空,【rightIndex - leftIndex == 1】返回节点

🍉递归三步曲

1、参数时元素数组,数组起始位置和终止位置;返回值是root

2、终止条件,遍历到叶子节点,也就是传入的数组大小为 1 时,就返回节点

3、单层逻辑:先找到数组中最大值和对应下标,构造根节点,递归调用函数,找到左右孩子

617.合并二叉树

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

思路:同时遍历两个树,通过前序遍历构造新的树,难就难在,它不是全部都需要遍历,可能一棵树很矮,另一棵树很高,这样的话就会有很多无效遍历,怎么确定一棵树被遍历完了呢?不如层序遍历,然后对应相加,再反向构造出来。

我想的是,把两个树层序遍历出来,之后用短的数字加到长的数组上面,再对数组进行for循环,按照中左右的方式构建节点,构建的时候还是要用上递归好像

尝试
class Solution {
    public TreeNode mergeTrees(TreeNode root1, TreeNode root2) {
        Queue<TreeNode> que = new ArrayList<>();
        List<Integer> list1 = getNums(que,root1);
        List<Integer> list2 = getNums(que,root2);
        if(list2.size()>list1.size()){
            List<Integer> temp = list1;
            list1 = list2;
            list2 = temp;
        }
        for(int i : list1){
            list2
        }

    }
    public List<Integer> getNums(Queue<TreeNode> que ,TreeNode node){
        List<Integer> result = new ArrayList<>();
        que.offer(node);
        while(!que.isEmpty()){
            TreeNode node = que.poll();
            result.add(node.val);
            if(node.left!=null){
                que.offer(node.left);
                result.add(node.left.val);
            };
            if(node.right!=null){
                que.offer(node.right);
                result.add(node.right.val);
            };        
        }
    }
}
答案
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;
    }
}
小结

🍉思路错了,因为题目没有说两棵树是满二叉树,可能出现最后一层,一个树是左节点,一个树是右节点

🍉卡尔直接改造了tree1,没有新建二叉树

🍉递归三步曲

1、参数:两个二叉树的根节点,返回值:合并后的根节点

2、终止条件:根据两个二叉树结点的情况,返回不同的值

3、单层递归逻辑:更新tree1对应节点的值,递归调用函数

700.二叉搜索树中的搜索

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

思路:思路有点乱,想要用前序遍历实现,但是写不出来

尝试
class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if(root == null) return null;
        if(root.val == val) return root;
        root.left = searchBST(root.left,val);
        root.right = searchBST(root.right,val);
        if(root.left.val == val ) return root.left;
        if(root.right.val == val ) return root.right;
        return null;
    }
}
答案
class Solution {
    // 递归,普通二叉树
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val) {
            return root;
        }
        TreeNode left = searchBST(root.left, val);
        if (left != null) {
            return left;
        }
        return searchBST(root.right, val);
    }
}

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);
        } else {
            return searchBST(root.right, val);
        }
    }
}

class Solution {
    // 迭代,普通二叉树
    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;
    }
}


// 迭代,利用二叉搜索树的特点
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;
    }
}
小结

🍉容易被旧题目的思路限制住,因为一开始写下的是【root.left】,起始没有必要得到左右孩子,只需要不断向下递归,去找目标值就行

🍉二叉搜索树

二叉搜索树是一个有序树:

  • 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  • 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  • 它的左、右子树也分别为二叉搜索树
     

98.验证二叉搜索树

题目:98. 验证二叉搜索树 - 力扣(LeetCode)

思路:中序遍历,每个节点的左边都要小于中节点,小于右节点,否则返回false,问题是,左右孩子为空的情况下怎么对比三个数值,遍历到叶子节点要怎么处理?

尝试(部分AC)
class Solution {
    public boolean isValidBST(TreeNode root) {
        if(root == null) return false;
        if(root != null && root.left == null && root.right == null) return true;
        if(root.left == null && root.right == null) return false;

        int leftValue = root.left == null ? Integer.MIN_VALUE : root.left.val;
        int rightValue = root.right == null ? Integer.MAX_VALUE : root.right.val;
        if(leftValue < root.val && root.val < rightValue) return true;

        if(root.left!=null) return isValidBST(root.left);
        if(root.right!=null) return isValidBST(root.right);
        return false;
    }
}
答案
// 简洁实现·递归解法
class Solution {
    public boolean isValidBST(TreeNode root) {
        return validBST(Long.MIN_VALUE, Long.MAX_VALUE, root);
    }
    boolean validBST(long lower, long upper, TreeNode root) {
        if (root == null) return true;
        if (root.val <= lower || root.val >= upper) return false;
        return validBST(lower, root.val, root.left) && validBST(root.val, upper, root.right);
    }
}
小结

🍉MIN_VALUE和MAX_VALUE考虑到了

🍉【左右孩子的判空是没必要的】因为你递归传进去之后,会有终止条件对【null】的情况进行处理

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值