您的位置:首页 > 其它

连续子数组求和

2018-01-08 15:39 190 查看

LINTCODE 402 - 连续子数组求和

今天,求LINTCODE娘给我题目的时候,给了我这么一个充满回忆的题目,这个题目可谓是倾倒众生,一遍又一遍地出现,居家旅行面试必备,我也就着记忆里的印象,将当初看到这个最佳解法时的惊艳写出来和各位读者分享一下。

================================================================================================================

已知
给定一个整数数组,请找出一个连续子数组,使得该子数组的和最大。输出答案时,请分别返回第一个数字和最后一个数字的下标。(如果两个相同的答案,请返回其中任意一个)

示例
给定 [-3, 1, 3, -3, 4], 返回[1,4].

================================================================================================================

思路如下

 记录一个最大值,暂时不考虑数组全是负数的情况,默认为0
 -3 为 负数,舍弃,进入下一个数字
 1 为正数,默认当前最大值为1, 开始和结束下标为1,1
 1 + 3  为4,正数,且比最大值1要大,最大值改为4,开始和结束下标为1,2
 4 + -3  为1,正数,但是值比最大值小了,不处理
 1 + 4  为5, 正数,且比最大值4要大,最大值改为5,开始和结束下标位1,4
 遍历完成,当前最大值为5,开始和结束下标位1,4

这个一个复杂度为O(n)的算法。

================================================================================================================

这个算法的正确性,我们来观察一下:[... start ...
end ...],最佳答案的特征

 start和end代表的数字应该是正数,且如果start和end不是边界,start左边和end右边的数字应该是负数

这里有点意会的意味了,其实我们的算法就是遍历了从每个可以作为开始下标的数字开始的最大值,然后从所有的最大值中选最大的,找出得出这个值时的开始和结束下标。

================================================================================================================

public class Solution {
public List<Integer> continuousSubarraySum(int[] A) {
if (onlyMinusDigit(A)) {
int index = getMaxIndex(A);
List<Integer> ret = new ArrayList<Integer>();
ret.add(index);
ret.add(index);
return ret;
}

int maxvalue = 0;
int temp = 0;
int start = 0;
int[] index = new int[2];

for (int i = 0; i < A.length; i++) {
temp += A[i];
if (temp < 0) {
temp = 0;
start = i + 1;
}
if (temp > maxvalue) {
maxvalue = temp;
index[0] = start;
index[1] = i;
}
}

List<Integer> ret = new ArrayList<Integer>();
ret.add(index[0]);
ret.add(index[1]);
return ret;
}

private static int getMaxIndex(int[] a) {
int maxvalue = a[0];
int index = 0;
for (int i = 1; i < a.length; i++) {
if (a[i] > maxvalue) {
index = i;
}
}
return index;
}

private static boolean onlyMinusDigit(int[] a) {
for (int num : a) {
if (num >= 0) {
return false;
}
}
return true;
}
}

谢谢您的阅读,希望您意会到了这个算法的精髓,这样想必不需要看我的代码,就能在源代码基础上找到如何得出start和end下表的方法,^_^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  连续子数组求和