数组连续子数组最大和最大乘积
2013-07-24 07:18
405 查看
题目:给定一个数组,要求其连续子数组的最大和。如数组为{6,-3,-2,7,-15,1,2,2},连续子数组的最大和为8(从第0个开始,到第3个为止)
解法1:首先最容易想到的便是利用枚举的方法,枚举出所有可能大小的连续子数组的和,然后选出其中最大的一个。即从连续子数组的大小为1一直到n,分别计算它们的和,最后选出使和最大的那个子数组。这种方法的实现比较简单,只需要三重循环即可。然而这种实现方法的复杂度是O(n^3),对于稍微大点的n,运行时间是不可接受的。由于实现方式比较简单,故此没有给出代码。
解法2:很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。
解法:当数组是首尾相连时,求连续子数组最大和的方法可以归纳如下:
1.将原数组进行扩充,即假设原数组为{1,2,-3,4,5},则扩充相当于{1,2,-3,4,5,1,2,-3,4,5}
2.利用上述的解法在扩充后的数组进行遍历求其连续子数组的最大和,不过要做一些小改动,即保证子数组的长度在原数组的长度范围之内。这样求出来的结果即是原数组首尾相连后,连续子数组的最大和。
注:当然,此处我们并不需要重新申请一个2倍原数组大小的额外空间,只需要在遍历的时候,下一个索引值采用mod n的方法。具体可以参见源代码。
代码:
题目:给定一个长度为n的数组,其中元素有正有负,求该数组的连续子数组的最大乘积。
解法:本题的解法分析可以参见July的博文:http://blog.csdn.net/v_july_v/article/details/8701148
解法1:首先最容易想到的便是利用枚举的方法,枚举出所有可能大小的连续子数组的和,然后选出其中最大的一个。即从连续子数组的大小为1一直到n,分别计算它们的和,最后选出使和最大的那个子数组。这种方法的实现比较简单,只需要三重循环即可。然而这种实现方法的复杂度是O(n^3),对于稍微大点的n,运行时间是不可接受的。由于实现方式比较简单,故此没有给出代码。
解法2:很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。
long getMaxSum(int *arr, int n, int &max_l, int &max_h) { if(arr == NULL || n == 0) return LONG_MIN; long max_sum = LONG_MIN; long sum = 0; //子数组当前累加值 int tmp_l = 0; //当前累加值的子数组起始索引 int tmp_h = 0; //当前累加值的子数组终止索引 for(int i = 0; i < n; i++) { sum += arr[i]; tmp_h = i; if(sum > max_sum) { max_sum = sum; max_l = tmp_l; max_h = tmp_h; } if(sum <= 0) { sum = 0; tmp_l = i+1; tmp_h = i+1; } } return max_sum; }变形题目:这个题目有一个变形。数组是首尾相连的,即相当于数组是一个环的结构,要求从这个环的结构中求出最大的和。
解法:当数组是首尾相连时,求连续子数组最大和的方法可以归纳如下:
1.将原数组进行扩充,即假设原数组为{1,2,-3,4,5},则扩充相当于{1,2,-3,4,5,1,2,-3,4,5}
2.利用上述的解法在扩充后的数组进行遍历求其连续子数组的最大和,不过要做一些小改动,即保证子数组的长度在原数组的长度范围之内。这样求出来的结果即是原数组首尾相连后,连续子数组的最大和。
注:当然,此处我们并不需要重新申请一个2倍原数组大小的额外空间,只需要在遍历的时候,下一个索引值采用mod n的方法。具体可以参见源代码。
代码:
/** *首尾相连连续子数组的最大和 *@param max_l:最终子数组的起始索引 *@param max_h:最终子数组的终止索引 *@return :返回最大的子数组的和 */ long getMaxSum(int *arr, int n, int &max_l, int &max_h) { if(arr == NULL || n == 0) return LONG_MIN; if(arr == NULL || n == 0) return LONG_MIN; long max_sum = LONG_MIN; long sum = 0; int tmp_l = 0; int tmp_h = 0; for(int k = 0; k < 2*n; k++) { int i = k % n; sum += arr[i]; tmp_h = k; if(tmp_h - tmp_l + 1 > n) { //确保子数组的长度不超过n sum -= arr[tmp_l%n]; tmp_l++; } if(sum > max_sum) { max_sum = sum; max_l = tmp_l; max_h = tmp_h; } if(sum <= 0) { sum = 0; tmp_l = k+1; tmp_h = k+1; } } return max_sum; }扩展:当要求的不是连续子数组的最大和,而是子数组的最大和该怎么求解呢?(提示:动态规划)
题目:给定一个长度为n的数组,其中元素有正有负,求该数组的连续子数组的最大乘积。
解法:本题的解法分析可以参见July的博文:http://blog.csdn.net/v_july_v/article/details/8701148
相关文章推荐
- 动态规划——最大连续子数组和(或乘积)
- 最大连续子数组和、乘积(动态规划)
- 连续子数组的最大乘积
- 求解连续子数组乘积的最大值
- 动态规划--求最大连续子数组的和(Python实现)&求解最大连续乘积字串(Python实现)
- LeetCode-152:Maximum Product Subarray (乘积最大连续子数组) -- medium
- 【LeetCode】Maximum Product Subarray 求连续子数组使其乘积最大
- 【LeetCode】152. Maximum Product Subarray最大连续子数组乘积
- Array-----152. Maximum Product Subarray(最大连续子数组乘积)
- 笔试题:求最大连续子数组的最大乘积
- 连续子数组的最大乘积、最小乘积
- 求连续子数组最大乘积
- 笔试面试算法经典--连续子数组的最大乘积及连续子数组的最大和(Java)
- 求连续子数组的最大乘积
- JAVA代码—算法基础:最大连续子数组乘积问题
- 求连续子数组最大乘积
- 长度为M的数组A,找出位置N,使得A[0]...A[N-1]和A[N]...A[M - 1]的和的乘积为最大。
- 求数组中最大连续子数组
- 最大连续子数组
- (剑指offer)最小的K个数 连续子数组的最大和