分治法避免定义多个递归函数,应该使用ResultType
总结:对二叉树应用分治法时,应避免定义多个递归函数,当出现需要递归求解多种的结果时,尽量使用ResultType来让一次递归返回多种结果。
题目:Binary Tree Maximum Path Sum
给出一棵二叉树,寻找一条路径使其路径和最大,路径可以在任一节点中开始和结束(路径和为两个节点之间所在路径上的节点权值之和)。
解法:定义两个函数,maxPathSum(TreeNode root)表示以root为根的树的最大路径长度(即题目所求,至少包含一个节点),rootToAny(TreeNode root)表示从根节点出发的所有路径长度的最大值(至少包含一个节点),则代码如下:
public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: An integer.
     */
    public int maxPathSum(TreeNode root) {
        // write your code here
        if(root==null)
            return Integer.MIN_VALUE;
        int pathWithoutRoot = Math.max(maxPathSum(root.left),maxPathSum(root.right));
        int pathWithRoot = Math.max(rootToAny(root.left),0)+Math.max(rootToAny(root.right),0)+root.val;
        return Math.max(pathWithoutRoot,pathWithRoot);
    }
    public int rootToAny(TreeNode root){
        if(root==null)
            return Integer.MIN_VALUE;
        return Math.max(0,Math.max(rootToAny(root.left),rootToAny(root.right)))+root.val;
    }
}
上面代码在lintcode能提交通过,但在leetcode提交则超时。
我们来分析它的时间复杂度,假设这颗树是一颗平衡二叉树,设maxPathSum函数的时间复杂度为T(n),rootToAny函数时间复杂度是t(n)。则递归式如下:
T(n) = 2T(n/2)+2t(n/2)+C
t(n) = 2t(n/2)+C
解得t(n) = O(n) , T(n) = O(n^2) .
如果我们只定义一个递归函数一次性返回两个值,能将递归式变为
T(n) = 2T(n/2)+C
解得T(n) = O(n).
时间复杂度将会大大降低。
在java中,可通过自己定义一个返回类型来实现返回多个值,代码如下:
public class Solution {
    /**
     * @param root: The root of binary tree.
     * @return: An integer.
     */
    private class ResultType {
        int singlePath, maxPath;
        ResultType(int singlePath, int maxPath) {
            this.singlePath = singlePath;
            this.maxPath = maxPath;
        }
    }
    private ResultType helper(TreeNode root) {
        if (root == null) {
            return new ResultType(Integer.MIN_VALUE, Integer.MIN_VALUE);
        }
        // Divide
        ResultType left = helper(root.left);
        ResultType right = helper(root.right);
        // Conquer
        int singlePath =
            Math.max(0, Math.max(left.singlePath, right.singlePath)) + root.val;
        int maxPath = Math.max(left.maxPath, right.maxPath);
        maxPath = Math.max(maxPath,
                           Math.max(left.singlePath, 0) +
                           Math.max(right.singlePath, 0) + root.val);
        return new ResultType(singlePath, maxPath);
    }
    public int maxPathSum(TreeNode root) {
        ResultType result = helper(root);
        return result.maxPath;
    }
}
类似的一题为求两个节点的最近公共祖先(LCA),不使用resultType的结果耗时900多ms,使用resultType仅耗时13ms。
分治法避免定义多个递归函数,应该使用ResultType的更多相关文章
- Leetcode Lect4 二叉树中的分治法与遍历法
		
在这一章节的学习中,我们将要学习一个数据结构——二叉树(Binary Tree),和基于二叉树上的搜索算法. 在二叉树的搜索中,我们主要使用了分治法(Divide Conquer)来解决大部分的问题. ...
 - 分治法(一)(zt)
		
这篇文章将讨论: 1) 分治策略的思想和理论 2) 几个分治策略的例子:合并排序,快速排序,折半查找,二叉遍历树及其相关特性. 说明:这几个例子在前面都写过了,这里又拿出来,从算法设计的策略的角度把它 ...
 - 分治法求一个N个元素数组的逆序数
		
背景 逆序数:也就是说,对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时, ...
 - (逆序对 分治法)P1908 逆序对 洛谷
		
题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定 ...
 - 分治法——快速排序(quicksort)
		
先上代码 #include <iostream> using namespace std; int partition(int a[],int low, int high) { int p ...
 - Leetcode之分治法专题-654. 最大二叉树(Maximum Binary Tree)
		
Leetcode之分治法专题-654. 最大二叉树(Maximum Binary Tree) 给定一个不含重复元素的整数数组.一个以此数组构建的最大二叉树定义如下: 二叉树的根是数组中的最大元素. 左 ...
 - 【LeetCode】分治法 divide and conquer (共17题)
		
链接:https://leetcode.com/tag/divide-and-conquer/ [4]Median of Two Sorted Arrays [23]Merge k Sorted Li ...
 - 分治法求解最近对问题(c++)
		
#include"stdafx.h" #include<iostream> #include<cmath> #define TRUE 1 #define F ...
 - ACM/ICPC 之 分治法入门(画图模拟:POJ 2083)
		
题意:大致就是要求画出这个有规律的Fractal图形了= = 例如 1 对应 X 2 对应 X X X X X 这个题是个理解分治法很典型的例子(详情请参见Code) 分治法:不断缩小规 ...
 
随机推荐
- Nginx+PHP-fpm高负载优化及压力测试方法
			
Nginx+PHP-fpm组合,以内存占用小,负载能力强壮的特点,成为小内存VPS建站的首选组合.我们一起来探讨一下nginx+php-fpm高负载的优化方法. 先来看看nginx配置参数的优化.ng ...
 - centos 7.0最小化安装 查看yum 所有安装的软件包~
			
使用命令 yum list installed [root@localhost ~]# yum list installed 已加载插件:fastestmirror base | 3.6 kB 00: ...
 - Mysql表分区几种方式
			
自5.1开始对分区(Partition)有支持,一张表最多1024个分区 查询分区数据: SELECT * from table PARTITION(p0) = 水平分区(根据列属性按行分)= 举个简 ...
 - Druid使用起步—在javaWeb项目中配置监控   连接池
			
当我们在javaWEB项目中使用到druid来作为我们的连接池的时候,一定不会忘了添加监控功能.下面我们就来看一下,在一个简单的web项目中(尚未使用任何框架)我们是如果来配置我们的web.xml来完 ...
 - OS命令注入
			
SSL http://kb.cnblogs.com/page/162080/ http://baike.baidu.com/link?url=jPitKuDw_ncDlMbOc1SkWzM9TuKX9 ...
 - spring之BeanFactoryAware接口
			
springBeanFactoryAware (转)要直接在自己的代码中读取spring的bean,我们除了根据常用的set外,也可以通过spring的BeanFactoryAware接口实现,只要实 ...
 - 【8-20】java学习笔记02
			
others 初始化块在构造器前执行: 静态初始化块和实例变量显示初始化执行顺序为各自定义的位置: final类不能派生子类,final方法不可覆盖,final变量不可重新赋值: 判定值相等,Stri ...
 - 简单实用的PHP防注入类实例
			
这篇文章主要介绍了简单实用的PHP防注入类实例,以两个简单的防注入类为例介绍了PHP防注入的原理与技巧,对网站安全建设来说非常具有实用价值,需要的朋友可以参考下 本文实例讲述了简单实用的PHP防注 ...
 - 高效率http页面优化法则一【JS对DOM的操作】
			
高效http页面优化法则一很多人都认为JS的效率太慢了,都不愿意用js来实现相对困难一点的程序逻辑.在这里我要说的是其实js的效率并不慢,慢的是DOM,如果操作好DOM,你的js效率将提高接近千倍(这 ...
 - 开始使用 Markdown
			
(Xee:我最近感觉nyfedit打开有点慢,数据库有点大,试想着用一些其他的方式记录一下学习的过程,才想起了遗忘了很长时间的Markdown,将其分类在HTML下,也是我原本意愿的...) 本文面向 ...