代码随想录-二叉树【2】(Java)

从中序和后序遍历序列构造二叉树

链接: 106.从中序与后序遍历序列构造二叉树
在这里插入图片描述

思路

具体思路见代码or思维导图

自己刚开始写时,思路非常混乱,应该用文字理清思路,在代码中注释后,再一步步想办法如何用代码诠释这些文字

后来各种小的报错

root.left和root.right不需要再次定义!在TreeNode的定义中已经将它们的定义写好了。

代码

class Solution {
    Map<Integer,Integer> map;
    TreeNode traversal(int[] inorder,int inBegin,int inEnd,int[] postorder,int postBegin,int postEnd){
        // 终止条件
        if (inBegin >= inEnd || postBegin >= postEnd){
            return null;
        }
        // 单层逻辑
        // 1.找到后序遍历序列最后一个元素在中序遍历队列中的位置
        int rootIndex = map.get(postorder[postEnd - 1]);
        // 创建节点
        TreeNode root = new TreeNode(inorder[rootIndex]);
        // 2.将中序队列分为中左区间和中右区间
        // 3.将后序队列按照中序队列的长度,分为后左区间和后右区间
        int lenOfLeft = rootIndex - inBegin;
        // 4.递归遍历
        // root.left和root.right,本来就是TreeNode类型,不需要再次定义
        root.left = traversal(inorder,inBegin,rootIndex,
                                    postorder,postBegin,postBegin + lenOfLeft);
        // root.left = traversal(inorder, inBegin, rootIndex,
        //                     postorder, postBegin, postBegin + lenOfLeft);
        root.right = traversal(inorder, rootIndex + 1, inEnd,
                            postorder, postBegin + lenOfLeft, postEnd - 1);

        return root;
    }
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        // 左闭右开区间
        map = new HashMap<>();
        for (int i = 0;i < inorder.length;i++){
            map.put(inorder[i],i);
        }
        return traversal(inorder,0,inorder.length,postorder,0,postorder.length);
    }
}

最大二叉树

链接: 654.最大二叉树

思路

思路非常简单

找到序列中的最大值,创建节点,然后再遍历最大值分隔出的左区间和右区间,用root.left和root.right进行接收

注意:用数组构造二叉树的题目,每次分隔尽量不要定义新的数组,而是通过下标索引直接在原数组上操作,这样可以节约时间和空间上的开销。

PS:因为题目给出的函数入口只有int[] nums;所以我们又定义了一个遍历函数。

代码

class Solution {
    TreeNode traversal(int[] nums,int begin,int end){
        if (begin >= end)   return null;
        int max = begin;
        // 找到序列中的最大值
        for (int i = begin + 1;i < end;i++){
            if (nums[i] > nums[max]){
                max = i;
            }
        }
        // 创建节点
        TreeNode root = new TreeNode(nums[max]);
        // 循环遍历左区间和右区间
        root.left = traversal(nums,begin,max);
        root.right = traversal(nums,max+ 1,end);

        return root;
    }
    public TreeNode constructMaximumBinaryTree(int[] nums) {
        // 左闭右开区间
        return traversal(nums,0,nums.length);
    }
}

合并二叉树

链接: 617.合并二叉树

感悟

代码并不困难,用代码把自己的思路写下来即可,如果有哪里不合适,说明自己的思维不对,需要吸取参考别人的思路。

写代码前,先把自己的思路分块用注释标注好,然后再去写这一块内容

代码

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

二叉搜索树中的搜索

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

思路

将自己的思路写下来即可

代码

class Solution {
    public TreeNode searchBST(TreeNode root, int val) {
        if (root == null || root.val == val)    return root;
        TreeNode result = null;
        if (val > root.val) result = searchBST(root.right,val); 
        if (val < root.val) result = searchBST(root.left,val); 

        return result;
    }
}

验证二叉搜索树

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

思路

思路一

一定要记住:对于二叉搜索树,中序遍历得到的数组,一定是有序数组,递增(不可以有相同元素)

思路二

边中序遍历,边比较。设置一个变量记录遍历时的前一个节点,比较前一个节点与当前节点的大小,不符合递增情况则false,遍历结束返回true

代码

//转化成列表的形式
class Solution {
    List<Integer> list = new ArrayList<>();
    void traversal(TreeNode root){
        if (root == null)   return;
        traversal(root.left);
        list.add(root.val);
        traversal(root.right);
    }
    public boolean isValidBST(TreeNode root) {
        traversal(root);
        for (int i = 1;i < list.size();i++){
            if (list.get(i) <= list.get(i - 1))  return false;
        }
        return true;
    }
}

//边中序遍历边比较
class Solution {
    TreeNode pre = null;
    public boolean isValidBST(TreeNode root) {
       if (root == null)    return true;
       boolean left = isValidBST(root.left);
       if (pre != null && pre.val >= root.val)   return false;
       pre = root;
       boolean right = isValidBST(root.right);
       return left && right;
    }
}

小tips:

在写完代码后,至少要写三个测试用例验证

两个系统给的,一个自己想想有无特殊情况。

二叉搜索树的最小绝对差

链接: 530.二叉搜索树的最小绝对差

思路

二叉搜索树中序遍历有序,所以最小绝对差一定是相邻两个元素相减。二叉搜索树中序遍历有序,所以最小绝对差一定是相邻两个元素相减。

代码

class Solution {
    List<Integer> list = new ArrayList<>();
    void traversal(TreeNode root){
        if (root == null)   return;
        traversal(root.left);
        list.add(root.val);
        traversal(root.right);
    }
    public int getMinimumDifference(TreeNode root) {
        traversal(root);
        // 因为要比较大小,不可以简单地为result赋一个值
        int result = Integer.MAX_VALUE;
        if (list.size() < 2) return 0;
        for (int i = 1;i < list.size();i++){
            result = Math.min(result,list.get(i) - list.get(i - 1));
        }
        return result;
    }
}

//边中序遍历边比较最小绝对差
class Solution {
    int result = Integer.MAX_VALUE;
    TreeNode pre = null;
    void traversal(TreeNode cur){
        if (cur == null)   return;
        traversal(cur.left);
        if (pre != null){
            result = Math.min(result,cur.val - pre.val);
        }
        pre = cur;
        traversal(cur.right);
    }
    public int getMinimumDifference(TreeNode root) {
        traversal(root);
        return result;
    }
}

二叉搜索树中的众数

链接: 501.二叉搜索树中的众数

思路

二叉搜索树有其特殊性,在有相同值的二叉树中,该二叉树中序遍历后得到的序列是不递减的。

在前面的题目中,我们知道如果不把二叉树转化成序列的形式,可以创建前一个节点pre,利用pre和cur的关系来进行比较。

本道题目,我想到了求出maxCount的方法,但如何将多个众数加入序列中,没有思路,这一点需要学习。

可以在比较count和maxCount时,对结果集进行操作,每次比较时,说明没有达到最大出现次数,将原有结果清空,加入最新结果。如果count=maxCount时,原有结果保留的同时,加入出现次数相同的元素

代码

class Solution {
    List<Integer> reList;
    int count;
    int maxCount;
    TreeNode pre;
    public int[] findMode(TreeNode root) {
        reList = new ArrayList<>();
        count = 0;
        maxCount = 0;
        pre = null;
        findMode1(root);

        int[] result = new int[reList.size()];
        for (int i = 0;i < reList.size();i++){
            result[i] = reList.get(i);
        }
        return result;
    }
    void findMode1(TreeNode cur){
        if (cur == null)    return;
        findMode1(cur.left);
        if (pre == null || pre.val != cur.val){
            count = 1;
        }else{
            count++;
        }
        //重要!!!!
        if (count > maxCount){
            maxCount = count;
            reList.clear();
            reList.add(cur.val);
        }else if(count == maxCount){
            reList.add(cur.val);
        }
        // 一定不要忘记移动pre呀!三四次了!
        pre = cur;
        findMode1(cur.right);
        return;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值