连续子数组求和

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下表的方法,^_^


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值