双非本科准备秋招(17.1)—— 力扣二叉树

1、257. 二叉树的所有路径

        要求返回根节点到叶子节点的所有路径,这里用前序遍历就好。

        每次递归前,都让字符串s加上当前节点的值和“->”,然后判断是否为叶子节点,如果是的话,说明这条路径是一个答案,因为最后多一个->,所以用substring去掉。

        如果root是null,那么root.left和root.right可能会空指针异常。所以每次递归的时候都要做一下判断。

class Solution {
    List<String> list = new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        String s = "";
        pre(root, s);
        return list;
    }
    public void pre(TreeNode root, String s){
        s += root.val+"->";
        if(root.left == null && root.right == null){
            list.add(s.substring(0, s.length()-2));
            return;
        }
        if(root != null && root.left != null) pre(root.left, s);
        if(root != null && root.right != null) pre(root.right, s);
    }
    
}

2、110. 平衡二叉树

        我用的比较好想的方法,直接用非递归的方式前序遍历每个节点,在出栈的时候进行检查,检查每个节点的左右孩子最大高度差是否符合要求。        

class Solution {
    public boolean isBalanced(TreeNode root) {
        LinkedList<TreeNode> stack = new LinkedList<>();
        while(root != null || !stack.isEmpty()){
            if(root != null){
                stack.push(root);
                root = root.left;
            }
            else{
                //检查
                TreeNode t = stack.pop();
                if(Math.abs(H(t.left) - H(t.right)) > 1){
                    return false;
                }
                root = t.right;

            }
        }
        return true;
    }
    public int H(TreeNode root){
        if(root == null) return 0;
        return Math.max(H(root.left), H(root.right))+1;
    }
}

3、222. 完全二叉树的节点个数

        直接遍历即可。

class Solution {
    public int countNodes(TreeNode root) {
        LinkedList<TreeNode> stack = new LinkedList<>();
        int cnt = 0;
        while(root != null || !stack.isEmpty()){
            if(root != null){
                cnt++;
                stack.push(root);
                root = root.left;
            }
            else{
                TreeNode t = stack.pop();
                root = t.right;
            }
        }
        return cnt;
    }
}

4、105. 从前序与中序遍历序列构造二叉树

        前序:1 2 4 3 6 7

        中序:4 2 1 6 3 7

首先,要确认根节点的值,根节点就是前序遍历的第一个节点。

于是我们得到根:1

然后在中序的数组中找到根,因为中序是 左根右 的顺序,所以根的左右两侧就是左子树

左:4 2

右:6 3 7

同样的,我们遍历左子树4 2,在前序中找到根,得到根是2,于是开始循环······

        观察以上内容,我们可以这样做:找到前序遍历的节点,然后循环遍历中序数组,找到第i个元素是根节点,这时候继续递归寻找左子树,左子树的前序数组下标为1~i,中序数组为0~i-1;右子树的前序数组下标为i+1~len-1,中序数组为i+1~len-1

        因为两个数组长度相同,所以判断退出条件写一个即可。

        当然这样效率比较低,但是确实比较好理解一些。

class Solution {
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        return buildByPreAndIn(preorder, inorder);
    }
        public TreeNode buildByPreAndIn(int[] pre, int[] in){
        if(pre.length == 0) return null;
        //根节点
        TreeNode root = new TreeNode(pre[0]);
        for(int i = 0; i < in.length; i++){
            if(root.val == in[i]){
                //区分左右子树 in是 0~i-1  i+1 ~ len-1   pre是1 ~ i  i+1 ~ len-1
                root.left = buildByPreAndIn(Arrays.copyOfRange(pre, 1, i+1), Arrays.copyOfRange(in, 0, i));
                root.right = buildByPreAndIn(Arrays.copyOfRange(pre, i+1, in.length), Arrays.copyOfRange(in, i+1, in.length));
                break;
            }
        }
        //每次返回根节点
        return root;
    }
}

class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

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

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

5、106. 从中序与后序遍历序列构造二叉树

        跟上一个题区别不大,后序最后一个数就是根节点,也是从中序数组中找到根,然后又分成左右子树······

        我们可以根据前序中序,也可以根据中序后序建树,但是不可以根据前序后序建树,因为前面两个方式,我们都可以通过前序或者后序明确得到根节点,然后根据中序划分左右子树,但是如果只有前序和后序,我们得到根节点之后,无法确定如何划分左右子树。

class Solution {
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        return buildByInAndPost(inorder, postorder);
    }
    public TreeNode buildByInAndPost(int[] in, int[] post){
        if(in.length == 0) return null;
        TreeNode root = new TreeNode(post[post.length - 1]);

        for(int i = 0; i < in.length; i++){
            if(in[i] == root.val){
                root.left = buildByInAndPost(Arrays.copyOfRange(in, 0, i), Arrays.copyOfRange(post, 0, i));
                root.right = buildByInAndPost(Arrays.copyOfRange(in, i+1, in.length), Arrays.copyOfRange(post, i, post.length-1));
                break;
            }
        }
        return root;
    }
}
public class TreeNode {
    public int val;
    public TreeNode left;
    public TreeNode right;

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

    public TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}
  • 11
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值