数组中 最大和 的子数组

题目:

输入一个整型数组,数据元素有正数也有负数,求元素组合成连续子数组之和最大的子数组,要求时间复杂度为O(n)。

例如:

输入的数组为1, -2, 3, 10, -4, 7, 2, -5,最大和的连续子数组为3, 10, -4, 7, 2,其最大和为18。

背景:

本题最初为2005年浙江大学计算机系考研题的最后一道程序设计题,在2006年里包括google在内的很多知名公司都把本题当作面试题。

由于本题在网络中广为流传,本题也顺利成为2006年程序员面试题中经典中的经典。

分析:

如果不考虑时间复杂度,我们可以枚举出所有子数组并求出他们的和。不过非常遗憾的是,由于长度为n的数组有O(n2)个子数组(即:n + n-1 + ... + 1=n(n+1)/2);而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n3)。

很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。

[cpp] view plaincopyprint?

  1. void MaxSum(int array[], unsigned int len)
  2. {
  3. if(NULL == array || len <=0){
  4. return;
  5. }
  6. int curSum = 0, maxSum = 0;
  7. int i = 0;
  8. for(i=0; i<len; i++){
  9. curSum += array[i];     // 累加
  10. if(curSum < 0){          // 当前和小于0,重置为0
  11. curSum = 0;
  12. }
  13. if(curSum > maxSum){ // 当前和大于最大和,则重置最大和
  14. maxSum = curSum;
  15. }
  16. }
  17. if(maxSum == 0){            // 最大和依然为0,说明数组中所有元素都为负值
  18. maxSum = array[0];
  19. for(i=1; i<len; i++){
  20. if(array[i] > maxSum){
  21. maxSum = array[i];
  22. }
  23. }
  24. }
  25. printf("maxSum: %d", maxSum);
  26. }
void MaxSum(int array[], unsigned int len)
{
	if(NULL == array || len <=0){
		return;
	}

	int curSum = 0, maxSum = 0;
	int i = 0;
	for(i=0; i<len; i++){
		curSum += array[i];		// 累加

		if(curSum < 0){			// 当前和小于0,重置为0
			curSum = 0;
		}

		if(curSum > maxSum){	// 当前和大于最大和,则重置最大和
			maxSum = curSum;
		}
	}

	if(maxSum == 0){			// 最大和依然为0,说明数组中所有元素都为负值
		maxSum = array[0];
		for(i=1; i<len; i++){
			if(array[i] > maxSum){
				maxSum = array[i];
			}
		}
	}

	printf("maxSum: %d", maxSum);
}

测试数组:

[cpp] view plaincopyprint?

  1. int array[] = {1, -2, 3, 10, -4, 7, 2, -5};     // 3, 10, -4, 7, 2 = 18
int array[] = {1, -2, 3, 10, -4, 7, 2, -5};		// 3, 10, -4, 7, 2 = 18

运行结果:

代码改进:

有时,需要输出最大和的子数组及其开始、结束下标,代码如下:

[cpp] view plaincopyprint?

  1. void MaxSum(int array[], unsigned int len)
  2. {
  3. if(NULL == array || len <=0){
  4. return;
  5. }
  6. int curSum = 0, maxSum = 0;
  7. int index_start = 0, index_end = 0;     // 初始化子数组最大和下标
  8. int i = 0;
  9. for(i=0; i<len; i++){
  10. curSum += array[i];     // 累加
  11. if(curSum < 0){          // 当前和小于0,重置为0
  12. curSum = 0;
  13. index_start = i+1;      // 调整子数组最大和的开始下标
  14. }
  15. if(curSum > maxSum){     // 当前和大于最大和,则重置最大和
  16. maxSum = curSum;
  17. index_end = i;          // 调整子数组最大和的结束下标
  18. }
  19. }
  20. if(maxSum == 0){            // 最大和依然为0,说明数组中所有元素都为负值
  21. maxSum = array[0];
  22. index_start = index_end = 0;                // 初始化子数组最大和下标
  23. for(i=1; i<len; i++){
  24. if(array[i] > maxSum){
  25. maxSum = array[i];
  26. index_start = index_end = i;        // 调整子数组最大和下标
  27. }
  28. }
  29. }
  30. // 输出最大和的子数组及其开始、结束下标
  31. printf("index_start: %d\nindex_end: %d\n", index_start, index_end);
  32. for(i=index_start; i<=index_end; i++){
  33. printf("%d\t", array[i]);
  34. }
  35. printf("\n\nmaxSum: %d", maxSum);
  36. }
void MaxSum(int array[], unsigned int len)
{
	if(NULL == array || len <=0){
		return;
	}

	int curSum = 0, maxSum = 0;
	int index_start = 0, index_end = 0;		// 初始化子数组最大和下标
	int i = 0;
	for(i=0; i<len; i++){
		curSum += array[i];		// 累加

		if(curSum < 0){			// 当前和小于0,重置为0
			curSum = 0;
			index_start = i+1;		// 调整子数组最大和的开始下标
		}

		if(curSum > maxSum){		// 当前和大于最大和,则重置最大和
			maxSum = curSum;
			index_end = i;			// 调整子数组最大和的结束下标
		}
	}

	if(maxSum == 0){			// 最大和依然为0,说明数组中所有元素都为负值
		maxSum = array[0];
		index_start = index_end = 0;				// 初始化子数组最大和下标
		for(i=1; i<len; i++){
			if(array[i] > maxSum){
				maxSum = array[i];
				index_start = index_end = i;		// 调整子数组最大和下标
			}
		}
	}

	// 输出最大和的子数组及其开始、结束下标
	printf("index_start: %d\nindex_end: %d\n", index_start, index_end);
	for(i=index_start; i<=index_end; i++){
		printf("%d\t", array[i]);
	}

	printf("\n\nmaxSum: %d", maxSum);
}

测试数组:

[cpp] view plaincopyprint?

  1. int array[] = {1, -2, 3, 10, -4, 7, 2, -5};     // 3, 10, -4, 7, 2 = 18
int array[] = {1, -2, 3, 10, -4, 7, 2, -5};		// 3, 10, -4, 7, 2 = 18

运行结果:

数组中最大和的子数组

时间: 2024-08-05 08:28:35

数组中 最大和 的子数组的相关文章

二维数组中的最大联通子数组

题目: 输入一个二维整形数组,数组里有正数也有负数. 求所有子数组的和的最大值. 思路: 总结:

输出一个数组中最大和的子数组并且和不溢出

组员 石鹤李海超 一.题目 输出一个数组中最大和的子数组,数组为int32型,有1000个数,保证最大子数组的和不溢出. 二.设计思想 随机产生一千个数的数组,求最大子数组和的过程中判断是否溢出,如果溢出,则输出溢出. 三.源代码 #include<iostream.h> long MAX(unsigned long arry[],int length) { unsigned long sum=arry[0]; unsigned long maxsum=arry[0]; for(int i=1

2.分治算法研究-搜索数组中的最大连续子集和 2014-3-11 11:37 阅读(16)

//分治算法研究var cc=consolefunction find_max_crossing_subarray(A,low,mid,high){    var max_left=mid,max_right=mid    var left_sum=0    var sum=0    for(var i=mid;i>=low;i--){        sum=sum+A[i]        if(sum>left_sum){            left_sum=sum           

0131 JavaScript数组中新增元素:修改数组索引、修改 length 长度、数组翻转

? 数组中可以通过以下方式在数组的末尾插入新元素: 数组[ 数组.length ] = 新数据; 1.5.1 通过修改 length 长度新增数组元素 可以通过修改 length 长度来实现数组扩容的目的 length 属性是可读写的 var arr = ['red', 'green', 'blue', 'pink']; arr.length = 7; console.log(arr); console.log(arr[4]); // undefined console.log(arr[5]);

求一个数组中和最小的连续子数组

#include<stdio.h> #define MAX_LENGTH 10 int main() { int a[MAX_LENGTH]={1,2,3,-2,4,-6,-8,5,3,1}; int i,j,beg,end,tmp,min=0x7fffffff; //beg和end分别为子数组中首末元素下标,min为无穷大的数 beg=end=tmp=0; for(i=0;i<MAX_LENGTH;++i) { tmp=a[i]; for(j=i+1;j<MAX_LENGTH;+

一个有N个整数元素的一维数组{A[0],A[1],....,A[N-1],A[N]},这个数组有很多连续的子数组,那么连续子数组之和的最大的一个的值是什么?

1.动态规划的思想解决 /** * 在时间复杂度为O(N)内找出数组中最大的子序列的累加和 */ public static int sumNum(int[] array) { int n = array.length; int all = array[n - 1], start = array[n - 1]; int count = 0; for (int i = n - 2; i >= 0; i--) { if ((start + array[i]) > array[i]) { start

将一个任意整数插入到已排列的整型数组中,插入后,数组中的数仍保持有序

实现代码: package homework; import java.util.Scanner; public class HomeWork { public static void main(String[] args) { //將输入的数字插入到一个有序的数组中的合适位置 Scanner input = new Scanner(System.in); System.out.println("请输入一个数字:"); int num = input.nextInt(); //有序的整

百度:在O(1)空间复杂度范围内对一个数组中前后连段有序数组进行归并排序

一.题目理解 题目:数组al[0,mid-1]和al[mid,num-1]是各自有序的,对数组al[0,num-1]的两个子有序段进行merge,得到al[0,num-1]整体有序.要求空间复杂度为O(1).注:al[i]元素是支持'<'运算符的. 数据结构第一章就讲了有序表合并,不过那时候是合并到新表,判断条件是while(i<len1||j<len2),然后把a1或者a2数组(只有一个,因为另一个必定已经完全插入进了c数组,这也是为什么while条件是“或”)后面的元素:如果数据结构

返回数组中的最大值和删除数组重复值-排序

//数组中最大值function getMax(arr){ //取该数组第一个值为最大值 var max=arr[0]; for(var i=0;i<arr.length;i++){ if(arr[i]>max){ max=arr[i] } } return max;} console.log(getMax([2,98,10,88])) /*--------------------------------------------------------------------*///删除数组重