【91 算法-基础篇】03.树

例题一:104. 二叉树的最大深度

在这里插入图片描述
采用两种递归算法。

Solution 1: top-down recursive solution

class Solution {
        //top-down recursive solution
        int ans = 0;
    public int maxDepth(TreeNode root) {
            find(root, 1);
            return ans;
    }
        public void find(TreeNode node, int depth){
                if(node == null)
                        return;
                if(node.left == null && node.right == null)
                        ans = Math.max(depth, ans);
                find(node.left, depth+1);
                find(node.right, depth+1);
        }
}

Solution 2: bottom-up recursive solution

class Solution {
        //bottom-up recursive solution
    public int maxDepth(TreeNode root) {
            int ans = find(root);
            return ans;
    }
        public int find(TreeNode node){
                if(node == null)
                        return 0;
                int leftAns = find(node.left);
                int rightAns = find(node.right);
                return Math.max(leftAns, rightAns)+1;
        }
}

例题二:100. 相同的树

在这里插入图片描述

方法一:递归

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if( p == null && q == null)
                return true;
            if(p == null || q == null)
                    return false;
            if(p.val != q.val)
                    return false;
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    }
}

方法二:迭代(BFS)

class Solution {
        public boolean check(TreeNode p, TreeNode q){
                if(p == null && q == null)
                        return true;
                if(p == null || q == null)
                        return false;
                return p.val == q.val;
        }
    public boolean isSameTree(TreeNode p, TreeNode q) {
            if(p == null && q == null)
                    return true;
            if(!check(p, q))
                    return false;
            Queue<TreeNode> pQ = new LinkedList<>();
            Queue<TreeNode> qQ = new LinkedList<>();
            pQ.add(p);
            qQ.add(q);
            while(pQ.size() > 0){
                    p = pQ.remove();
                    q = qQ.remove();
                    if(!check(p,q))
                            return false;
                    if(p != null){
                            pQ.add(p.left);
                            pQ.add(p.right);
                            qQ.add(q.left);
                            qQ.add(q.right);
                    }
            }
            return true;   
    }
}

例题三:129. 求根到叶子节点数字之和

在这里插入图片描述

方法一:DFS

class Solution {
        int res = 0;
    public int sumNumbers(TreeNode root) {
            if(root == null)
                    return res;
            helper(root, 0);
            return res;
    }
        public void helper(TreeNode node, int sum){
                int temp = sum * 10 + node.val;
                if(node.left == null && node.right == null)
                        res += temp;
                else{
                        if(node.left != null)
                                helper(node.left, temp);
                        if(node.right != null)
                                helper(node.right, temp);
                }
        }
}

方法二:BFS

class Solution {
    public int sumNumbers(TreeNode root) {
            int res = 0;
            if(root == null)
                    return res;
            Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
            queue.add(new Pair(root, 0));
            while(!queue.isEmpty()){
                    Pair<TreeNode, Integer> pair = queue.remove();
                    if(pair.getKey().left == null && pair.getKey().right == null)
                            res += pair.getValue() * 10 + pair.getKey().val;
                    if(pair.getKey().left != null)
                            queue.add(new Pair(pair.getKey().left, pair.getValue() * 10 + pair.getKey().val));
                    if(pair.getKey().right != null)
                            queue.add(new Pair(pair.getKey().right, pair.getValue() * 10 + pair.getKey().val));
            }
            return res;
    }
}

例题四:513. 找树左下角的值

#37
在这里插入图片描述

方法一:BFS

class Solution {
    public int findBottomLeftValue(TreeNode root) {
            int maxLevel = -1, level = 0, res = 0;
            Queue<TreeNode> queue = new LinkedList<>();
            queue.add(root);
            while(!queue.isEmpty()){
                    int size = queue.size();
                    for(int i = 0; i < size; i++){
                    TreeNode node = queue.remove();
                    if(level > maxLevel){
                            maxLevel = level;
                            res = node.val;
                    }
                    if(node.left != null)
                            queue.add(node.left);
                    if(node.right != null)
                            queue.add(node.right);
                    }
                    level++;
            }
            return res;
    }
}

方法二:DFS

class Solution {
    int maxLevel = -1, res = 0;
    public int findBottomLeftValue(TreeNode root) {
            preOrder(root, 0);
            return res;
    }
        public void preOrder(TreeNode node, int level){
                if(node == null)
                        return;
                level++;
                if(node.left == null && node.right == null && level > maxLevel){
                        maxLevel = level;
                        res = node.val;
                }
                preOrder(node.left, level);
                preOrder(node.right, level);   
        }
}

例题五:105. 从前序与中序遍历序列构造二叉树

#38
在这里插入图片描述
前序遍历和中序遍历,后序遍历和中序遍历,都可以生成唯一的一个二叉树,而前序遍历和后续遍历不可以。

前序遍历和中序遍历

前续遍历序列的第一个节点是二叉树的根节点,这个根节点的左子树节点都位于中序遍历序列根节点的左面,这个根节点的右子树节点都位于中序遍历序列根节点的右面,依次类推,通过递归的方式创建一个二叉树。

class Solution {
        int preIndex = 0;
        int[] preorder, inorder;
        HashMap<Integer, Integer> map = new HashMap<>();
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        this.preorder = preorder;
            this.inorder = inorder;
            for(int i = 0; i < inorder.length; i++){
                    map.put(inorder[i], i);
            }
            return helper(0, inorder.length - 1);
            
    }
        public TreeNode helper(int left, int right){
                if(left > right)
                        return null;
                TreeNode node = new TreeNode();
                node.val = preorder[preIndex++];
                int inIndex = map.get(node.val);
                node.left = helper(left, inIndex-1);
                node.right = helper(inIndex+1, right);
                return node;
        }
}

后序遍历和中序遍历

后续遍历序列的最后一个节点是二叉树的根节点,这个根节点的左子树节点都位于中序遍历序列根节点的左面,这个根节点的右子树节点都位于中序遍历序列根节点的右面,依次类推,通过递归的方式创建一个二叉树。

class Solution {
        int postIndex;
        Map<Integer, Integer> map;
        int[] inorder, postorder;
    public TreeNode buildTree(int[] inorder, int[] postorder) {
            this.inorder = inorder;
            this.postorder = postorder;
            map = new HashMap<>();
            for(int i = 0; i < inorder.length; i++){
                    map.put(inorder[i], i);
            }
            postIndex = postorder.length - 1;
            return helper(0, inorder.length-1);
            
    }
        public TreeNode helper(int left, int right){
                if(left > right)
                        return null;
                TreeNode node = new TreeNode();
                node.val = postorder[postIndex];
                postIndex--;
                int inIndex = map.get(node.val);
                node.right = helper(inIndex + 1, right);
                node.left = helper(left, inIndex - 1);
                return node;
        }
}

例题六:124. 二叉树中的最大路径和

在这里插入图片描述

思路

从树的叶子节点开始考虑,它的最大路径和max_gain就是它本身的值。它的父节点的max_gain和考虑了它的左子树和右子树的max_gain(其实叶子节点也是),它本身的max_gain就是它的左右子树的max_gain加上父节点的值(如果左右子树的max_gain中有负数,我们就取0,相当于不算它)。我们对树中的每一个节点都求一下它的max_gain,取最大值即可。值得注意的是,每一个节点作为根节点的子树对它的父节点的max_gain是它的值加上左右子树max_gain中较大的那个。

代码

class Solution {
                int max_sum = Integer.MIN_VALUE;
        public int maxPathSum(TreeNode root) {
                max_gain(root);
                return max_sum;
    }
        public int max_gain(TreeNode node){
                if(node == null)
                        return 0;
                int left_gain = Math.max(0, max_gain(node.left));
                int right_gain = Math.max(0, max_gain(node.right));
                int connectSum = left_gain + right_gain + node.val;
                max_sum = Math.max(max_sum, connectSum);
                return node.val + Math.max(left_gain, right_gain);
        }
}

复杂度

  • 时间复杂度 O ( n ) O(n) O(n),n为节点的数量
  • 空间复杂度 O ( n ) O(n) O(n),最坏的情况下,skewed binary tree
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值