【Lintcode】628. Maximum Subtree

题目地址:

https://www.lintcode.com/problem/maximum-subtree/description

给定一棵二叉树,求其和最大的子树,返回其树根。

法1:分治。由于结果只有三种可能,要么在左子树中,要么在右子树中,要么就是root本身,所以可以用分治来做。但需要注意的是,由于要求一下当前树的节点和,就需要递归求解左右子树的节点和,如果不记录下来的话就会造成重复计算的问题。所以我们用一个哈希表记录每个子树的节点和是多少,做一下记忆化。代码如下:

import java.util.HashMap;
import java.util.Map;

public class Solution {
    /**
     * @param root: the root of binary tree
     * @return: the maximum weight node
     */
    public TreeNode findSubtree(TreeNode root) {
        // write your code here
        if (root == null) {
            return root;
        }
        
        Map<TreeNode, Integer> map = new HashMap<>();
        // 空树节点和记为0
        map.put(null, 0);
        return find(root, map);
    }
    
    private TreeNode find(TreeNode root, Map<TreeNode, Integer> map) {
        if (root == null) {
            return null;
        }
        
        TreeNode left = find(root.left, map), right = find(root.right, map);
        // 分别计算本树以及左右子树的节点和,
        // 由于是递归计算的,所以算完root节点和后左右子树的节点和都已经存在哈希表里了,可以直接拿出来
        int sum = sum(root, map), lSum = map.get(left), rSum = map.get(right);
        if (left == null && right == null) {
            return root;
        } else if (right == null) {
            return sum >= lSum ? root : left;
        } else if (left == null) {
            return sum >= rSum ? root : right;
        } else {
            if (sum >= Math.max(lSum, rSum)) {
                return root;
            } else {
                return lSum >= rSum ? left : right;
            }
        }
    }
    
    private int sum(TreeNode root, Map<TreeNode, Integer> map) {
    	// 如果已经有了记忆则调取记忆
        if (map.containsKey(root)) {
            return map.get(root);
        }
        // 否则递归求解并把结果放进哈希表
        map.put(root, sum(root.left, map) + sum(root.right, map) + root.val);
        // 最后返回
        return map.get(root);
    }
}

class TreeNode {
    int val;
    TreeNode left, right;
    TreeNode(int x) {
        val = x;
    }
}

时空复杂度 O ( n ) O(n)

法2:DFS。用全局变量记录已经找到的最大和和树根,然后边DFS边计算当前子树的和,边更新全局变量。代码如下:

public class Solution {
    int maxSum = Integer.MIN_VALUE;
    TreeNode res = null;
    /**
     * @param root: the root of binary tree
     * @return: the maximum weight node
     */
    public TreeNode findSubtree(TreeNode root) {
        // write your code here
        if (root == null) {
            return root;
        }
        // 计算所有子树的和并更新全局变量
        sum(root);
        return res;
    }
    
    private int sum(TreeNode root) {
        if (root == null) {
            return 0;
        }
        // 分治
        int left = sum(root.left), right = sum(root.right);
        int total = left + right + root.val;
        if (maxSum < total) {
            maxSum = total;
            res = root;
        }
        
        return total;
    }
}

时间复杂度 O ( n ) O(n) ,空间 O ( h ) O(h)

发布了387 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/105467790