LintCode-596: Minimum Subtree

这道题我感觉并不是很简单,因为递归的同时还要考虑SUM,但是又只能返回TreeNode *。
我用的递归,并假定NULL节点的SUM为0。用的全局变量来保存minValue和RecordNode。
这题要注意的地方:是当某个节点的左子节点或右子节点是NULL时,不能直接设minChildSum=min(sumLeft, sumRight); 因为NULL节点的SUM为0,所以肯定最小。测试特例:input = {1,#,2}。

代码如下:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the root of binary tree
     * @return: the root of the minimum subtree
     */
    TreeNode * findSubtree(TreeNode * root) {
        if (!root) return NULL;
        int sumLeft = sumSubTree(root->left);
        int sumRight = sumSubTree(root->right);
        int sumAll = sumLeft + sumRight + root->val;
        int minChildSum;
        if (!root->left) 
            minChildSum = sumRight;
        else if (!root->right) 
            minChildSum = sumLeft;
        else 
            minChildSum = min(sumLeft, sumRight);
        
        if (sumAll < minValue) {
            minValue = sumAll;
            recordNode = root;
        } else if (minChildSum < minValue) {
            minValue = minChildSum;
            recordNode = (sumLeft< sumRight)? root->left : root->right; 
        }
   
        return recordNode;
    }

private:
    int sumSubTree(TreeNode * root) {
        if (!root) 
            return 0;
        else {
            int sum = sumSubTree(root->left) + sumSubTree(root->right) + root->val; 
            if (sum < minValue) {
                minValue = sum;
                recordNode = root;
            }
            return sum;  
        }
    }

    int minValue=INT_MAX;
    TreeNode *recordNode;
};

另外,我看了一下九章的方法是将返回类型包装成一个结构,包括TreeNode*, sum和minSum。这个技巧值得学习。
其参考代码如下,需要好好掌握。

// version 2: Pure divide conquer
class ResultType {
    public TreeNode minSubtree;
    public int sum, minSum;
    public ResultType(TreeNode minSubtree, int minSum, int sum) {
        this.minSubtree = minSubtree;
        this.minSum = minSum;
        this.sum = sum;
    }
}

public class Solution {
    /**
     * @param root the root of binary tree
     * @return the root of the minimum subtree
     */
    public TreeNode findSubtree(TreeNode root) {
        ResultType result = helper(root);
        return result.minSubtree;
    }
    
    public ResultType helper(TreeNode node) {
        if (node == null) {
            return new ResultType(null, Integer.MAX_VALUE, 0);
        }
        
        ResultType leftResult = helper(node.left);
        ResultType rightResult = helper(node.right);
        
        ResultType result = new ResultType(
            node,
            leftResult.sum + rightResult.sum + node.val,
            leftResult.sum + rightResult.sum + node.val
        );
        
        if (leftResult.minSum <= result.minSum) {
            result.minSum = leftResult.minSum;
            result.minSubtree = leftResult.minSubtree;
        }
        
        if (rightResult.minSum <= result.minSum) {
            result.minSum = rightResult.minSum;
            result.minSubtree = rightResult.minSubtree;
        }
        
        return result;
    }
}

另外,发现还可以用超简洁的分治+遍历来解决这个问题(参考九章),代码如下:

class Solution {
public:
    /**
     * @param root: the root of binary tree
     * @return: the root of the minimum subtree
     */
    TreeNode * findSubtree(TreeNode * root) {
        helper(root);
        return recordRoot;
    }

private:
    int helper(TreeNode * root) {
        if (!root) 
            return 0;
            
        int sum = helper(root->left)+helper(root->right)+root->val;
        if (sum < minSum) {
            recordRoot = root;
            minSum = sum;
        }
        return sum;
    }

    int minValue=INT_MAX;
    TreeNode *recordNode;
};

三刷:

/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */

class Solution {
public:
    /**
     * @param root: the root of binary tree
     * @return: the root of the minimum subtree
     */
    TreeNode* findSubtree(TreeNode *root) {
        helper(root);
        return minNode;
    }
    
private:
    int helper(TreeNode *root) {
        if (!root) return 0;
        if (!root->left && !root->right) {
            if (root->val < minSum) {
                minSum = root->val;
                minNode = root;
            }
            return root->val;
        }
        int resLeft = helper(root->left);
        int resRight = helper(root->right);
        int resSelf = resLeft + resRight + root->val;
        if (resLeft && resLeft < resRight && resLeft < resSelf && resLeft < minSum) {
            minSum = resLeft;
            minNode = root->left;
        } else if (resRight && resRight < resLeft && resRight < resSelf && resRight < minSum) {
            minSum = resRight;
            minNode = root->right;
        } else if (resSelf < minSum) {
            minSum = resSelf;
            minNode = root;
        }
        return resSelf;
    }
    int minSum = INT_MAX;
    TreeNode *minNode = nullptr;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值