题目:
输入一个整型数组,数据元素有正数也有负数,求元素组合成连续子数组之和最大的子数组,要求时间复杂度为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)。
很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。
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);
}
测试数组:
int array[] = {1, -2, 3, 10, -4, 7, 2, -5}; // 3, 10, -4, 7, 2 = 18
运行结果:
代码改进:
有时,需要输出最大和的子数组及其开始、结束下标,代码如下:
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);
}
测试数组:
int array[] = {1, -2, 3, 10, -4, 7, 2, -5}; // 3, 10, -4, 7, 2 = 18
运行结果:
源码
参考推荐:
子数组的最大和[算法]
微软、Google等面试题
分享到:
相关推荐
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。 求所有子数组的和的最大值。要求时间复杂度为O(n)。 例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2, 因此...
从头到尾逐个累加示例数组中的每个数字。初始化和为0,第一步加上第一个数字1,...第八步加上最后一个数字-5,由于得到的和为13,小于此前最大和18,因此最终最大的子数组的和为18,对应的子数组是{3,10,-4,7,2}。
给定一个二维数组,由其中若干邻近元素构成的矩形称为子数组,请编写程序计算所有子数组元素之和的最大值。 【输入数据】第一行为整数N,代表二维数组的大小为N*N。接下来的N*N个整数被空格和换行符隔开,表示按照行...
求一个数组子数组的最大和,这是一道非常经典的公司面试或笔试题目,我分别使用了暴力枚举、分枝界定、动态规划三种算法实现。
给定一个二维数组,由其中若干邻近元素构成的矩形称为子数组,请编写程序计算所有子数组元素之和的最大值。 【输入数据】第一行是一个整数N,表示二维数组的大小为N*N。接下来的N*N个数被空格和换行符隔开,表示按照...
求一个二维数组中最大连通子数组的和
例如,对于数组[1, -2, 3, -4, 5],Kadane's Algorithm会得到子数组[3, -4, 5],因为它们的和是4,是所有子数组中最大的。 这个问题的应用非常广泛,尤其是在处理动态数据流或需要实时计算局部最优解的场景。例如,...
假设你有一个数组,而且这个数组中包含了数字的子数组,而我们要做的是从数组中的每个子数组中返回其最大的那个最大数。 基本解决方案 function largestOfFour(arr) { var results = []; // 创建一个results变量来...
4. **分治法**:对于大型数组,可以使用分治策略,将数组分为两半,递归地找最大值和最小值,然后比较两个子数组的结果。这种方法在数据量大且深度足够的情况下能提高效率。 在实际应用中,为了优化性能,还可以...
2. **解决**:递归地在每个子数组中寻找最大值和最小值。 3. **合并**:将两个子数组的最大值和最小值进行比较,从而得出整个数组的最大值和最小值。 #### 三、代码实现详解 下面是具体的代码实现,该程序采用 C ...
连续子数组的最大和是动态规划中的一个经典问题,它们要求我们在给定的数组中找到一个连续的子数组,使得该子数组的和最大。这种问题的解决方法有很多,我们今天将介绍两种不同的方法来解决这个问题。 方法一:贪心...
数组 求连续子序列最大和程序 时间复杂度O(n) 空间复杂度O(1)
3. **合并阶段**:遍历从 `mid-1` 到 `0`,计算以每个索引为起点向右延伸的最大子数组和。同时,遍历从 `mid+1` 到 `n-1`,计算以每个索引为起点向左延伸的最大子数组和。这两个过程可以使用动态规划的思想进行优化...
题目 "乘积最大子数组(动态规划)1" 是一道典型的动态规划问题,来源于 LeetCode 平台。问题要求在给定的整数数组 `nums` 中找出乘积最大的连续子数组,并返回这个子数组的最大乘积。动态规划是一种解决复杂问题的...
3. 记录:在遍历过程中,每一步都更新当前的最大乘积,最后返回的就是整个数组的最大子数组乘积。 除了动态规划,还可以采用 Kadane's Algorithm(卡丹诺算法)来解决这个问题。Kadane's Algorithm 是一种更简洁的...
本篇文章将详细探讨如何使用汇编语言编写程序来找出数组中的最大值和最小值。 首先,我们需要了解汇编语言的基本概念。在汇编语言中,我们使用指令来表示计算机的操作,如加载(LOAD)、存储(STORE)、加法(ADD)...
利用C语言可以实现对数组的各种操作,如输入数组元素,输出数组元素、求数组元素平均值、输出数组元素最大值、输出数组元素最小值、查找某数值元素是否存在、给数组元素排序等功能。本压缩文件中是上述功能对应的...
分而治之的思想解决求一个数组的最大子集,有效的降低了时间复杂度,值得学习。
通过上述分析可以看出,递归算法在解决数组最大值问题时具有很好的实用性和可读性。虽然递归算法存在一定的局限性,但在处理相对较小的数据集时,其简洁性和直观性使其成为一种非常有用的技术手段。