剑指Offer面试题31(java版):连续子数组的最大和

题目:输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。

求所有子数组的和的最大值。要求时间复杂度为O(n)

例如输入的数组为{1,-2,3,10,-4,7,2,-5}

看到该题目,很多人都能想到最直观的方法,即枚举出数组的所有子数组并求出他们的和。一个长度为n的数组,总共有n(n+1)/2个子数组。计算出所有的子数组的和,最快也需要O(n2)的时间。通常最直观的方法不会是最优的方法,面试官将提示我们还有更快的方法。

解法一:举例分析数组的规律:

我们试着从头尾逐个累加示例数组中的每个数字。初始化和为0.第一步加上第一个数字,此时和为1.接下来第二步加上数字-2,和就编程了-1.第三步加上数字3.我们注意到由于此前累计的和为-1,小于0,那如果用-1加3,得到的和为2,比3本身还小。也就是说从第一个数字开始的子数组的和会小于从第三个数字开始的子数组的和。因此我们不用考虑从第一个子数组,之前累计的和也被抛弃。

我们从第三个数字重新开始累加,此时得到的和为3.接下来第四步加10,得到和为13.第五步加上-4,和为9.我们发现-4是一个负数,因此累加-4之后得到的和比原来的还小。因此我们要把之前得到的和13保存下来,它有可能是最大的子数组的和。第六步加上数字7,9加7的结果是16,此时和比之前最大的和13还要大,把最大的子数组的和由13更新为16.第七步加上2,累加得到的和为18,同时我们也要更新最大子数组的和。第八步加上最后一个数字-5,由于得到结果为13,小于此前得到的最大和18,因此最终最大的子数组的和为18,对应的子数组是{3,10,-4,7,2}。

把过程分析清楚之后,我们用Java代码实现:

/**
 * 输入一个整型数组,数组里有正数也有负数。数组中一个或连续的多个整数组成一个子数组。
 * 求所有子数组的和的最大值。要求时间复杂度为O(n)
 */
package swordForOffer;

/**
 * @author JInShuangQi
 *
 * 2015年8月8日
 */
public class E31GreatestSumOfSubarrays {

	public Integer findGreatestSum(int[] arr){

		if(arr.length ==0)
			return null;
		int greatest = 0x80000000;
		int curSum = 0;
		for(int i = 0;i<arr.length;i++){
			if(curSum <= 0)
				curSum = arr[i];
			else
				curSum += arr[i];
			if(curSum >greatest)
				greatest = curSum;
		}
		return greatest;
	}
	public static void main(String[] args){
		int[] arr={-1,-2,-3,-10,-4,-7,2,-5};
		E31GreatestSumOfSubarrays test = new E31GreatestSumOfSubarrays();
		System.out.println(test.findGreatestSum(arr));
	}
}

解法二:应用动态规划法

我们还可以适用动态规划的思想来分析这个问题。如果用函数f(i)表示以第i个数字结尾的子数组的最大和,那么我们需要求出max[f(i)],其中0<=i<n。我们可以使用能够下面的递归公示求f(i):

这个公式的意义:当以第i-1个数字结尾的子数组中所有的数字的和小于0时,如果把这个负数与第i个数累加,得到的结果比第i个数字本身还要小,所以这种情况下以第i个数字结尾的子数组就是第i个数字本身。如果以第i-1个数字结尾的子数组中所有的数字的和大于0,与第i个数字累加就得到以第i个数字结尾的子数组中所有的数字的和。

虽然我们用递归的方法分析动态规划的问题,但最终都会基于循环去编码。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-29 03:15:57

剑指Offer面试题31(java版):连续子数组的最大和的相关文章

剑指OFFER之最大子向量和(连续子数组的最大和)(九度OJ1372)

题目描述: HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天JOBDU测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止).你会不会被他忽悠住? 输入: 输入有多组数据,每组测试数据包括两行. 第一行为一个整数n(0<=n<=100000),当

剑指offer面试题14(Java版):调整数组顺序使奇数位于偶数的前面

题目:输入一个整数数组.实现一个函数来调整该数组中数字的顺序.使得全部奇数位于数组的前半部分.全部偶数位于数组的后半部分. 1.基本实现: 假设不考虑时间复杂度,最简单的思路应该是从头扫描这个数组,每碰到一个偶数时,拿出这个数字,并把位于这个数字后面的全部的数字往前面挪动一位. 挪完之后在数组的末尾有一个空位.这时把该偶数放入这个空位. 因为没碰到一个偶数就须要移动O(n)个数字.因此总的时间复杂度是O(n2).可是,这样的方法不能让面试官惬意.只是假设我们在听到题目之后立就可以以说出这个解法,

《剑指Offer》——Singleton(Java版)

1.单例模式的定义 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例. 2.单例模式的特点 单例类只能有一个实例. 单例类必须自己创建自己的唯一实例. 单例类必须给所有其他对象提供这一实例. 3.单例模式的Java代码 单例模式分为懒汉式(需要才去创建对象)和饿汉式(创建类的实例时就去创建对象). 4.饿汉式 在静态代码块实例对象 //在静态代码块实例对象 public class Singleton { private static Singleton singleton

剑指offer面试题31连续子数组的最大和

一.题目描述 HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学.今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决.但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止).你会不会被他忽悠住? 二.解题思路 求连续子数组的最大和,首先想的到最笨的方法就是暴力解决,两个for循环,遍历数组找到和最大的子

二叉树层次遍历(剑指Offer面试题32:从上到下打印二叉树)

图1所示为二叉树的层次遍历,即按照箭头所指方向,按照1.2.3的层次顺序,对二叉树每个节点进行访问 (此图反映的是自左至右的层次遍历,自右至左的方式类似). 要进行层次遍历,需要建立一个队列.先将二叉树头节点入队列,然后出队列,访问该节点, 如果它有左子树,则将左子树的根结点入队:如果它有右子树,则将右子树的根结点入队.然后出队列,对出队节点访问, 如此反复直到队列为空为止. 1 import java.util.*; 2 class TreeNode 3 { 4 int val; 5 Tree

剑指offer面试题29:数组中出现次数超过一半的数字

题目:数组中有一个数字出现的次数超过数组长度的一般,请找出这个数字,例如输入一个长度为9的数组(1,2,3,2,2,2,5,4,2,).由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. 个人第一眼想法是通过一个sort函数,再判断中间那数出现次数,只要出现多于n/2,就直接输出. 一般来说,最为直观的算法面试官都不会满意,那么有没有更优的算法呢? 这种算法是受快速排序算法的启发.在随机快速排序算法中,我们现在数组中随机选择一个数字,然后调整数组中数字的顺序,使得比选中的数字小的数字

【剑指Offer面试题】二维数组中的查找

下决心AC所有剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有好处的.加油~ 二维数组中的查找 时间限制:1 秒内存限制:32 兆 特殊判题:否提交:19005解决:3642 题目描述: 在一个

【剑指Offer面试题】九度OJ1384:二维数组中的查找

下决心AC全部剑指offer面试题. 九度OJ面试题地址:http://ac.jobdu.com/hhtproblems.php 书籍:何海涛--<剑指Offer:名企面试官精讲典型编程题> 对于面试题,面试官往往更希望我们能提出优化方法,这样更能体现我们的思维能力以及传说中的"内功".所以做剑指offer要着重训练这方面,多总结多细究,总是有优点的.加油~ 题目链接地址: http://ac.jobdu.com/problem.php?pid=1384 二维数组中的查找

【剑指Offer面试题】 九度OJ1516:调整数组顺序使奇数位于偶数前面

题目链接地址: http://ac.jobdu.com/problem.php?pid=1516 题目1516:调整数组顺序使奇数位于偶数前面 时间限制:1 秒内存限制:128 兆特殊判题:否提交:2858解决:924 题目描写叙述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得全部的奇数位于数组的前半部分,全部的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 输入: 每一个输入文件包括一组測试案例. 对于每一个測试案例.第一行输入一个n,代表该数组