看大神文章小结——微软面试3

大神 地址 :http://blog.csdn.net/v_JULY_v/article/details/6015165

3.求子数组的最大和(数组)
题目:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,
因此输出为该子数组的和18。


这一题 一看题目 有点发懵。不知道怎么下手。

第一个想法 将临近的负数 看成一个整体 临近的整数看成一个整体 应该会简化这个题目吧。  这样 就变成了 一个正数 一个负数 相隔着的数组。 + - + - + - +  - +  - +      然后呢?

想了一下 以一个 正数为中心 向两边扩展。  只要 一组 (+ -) 和大于0 就是可以用的。 如果小于零 一组 (+ - )等于是负数。问题走不通。 这样首先无法确定 以中心的那个数。可能这个思路走不通了。换一个思路

思路2  以前了解过 这种一个数组中间N个之后 可以用一个缓存数组 记录着每个元素之前的和 然后相减得到。 比如 一个数组

num[1,2,3,4,5,6] 可以 遍历得到另外一个数组 sum[1,2,6,10,15,16] 这样 求中间 比如 从第n个数到第m个数 就可以通过sum[(m-1)]-sum[(n-1-1)]  减一时 数组从0开始 第二个减一 是因为 要包含第一个数字。 如果n-1-1为负数了 那么 就是0. 可以建立一个这样的数组。然后遍历 可能就会简单一点。

需要注意的是 题目是需要输出和的值 不需要知道是那几个数。所以这个就是关键点!!!!

思路出来了。遍历sum数组。 首先 初始化最小值,最大值,以及最大的和 三个参数 returnData, nowMinData, nowMaxData,开始遍历。 

如果越到比最大值还大的 ok 更新最大值 更新 最大的和(判断当前的最大和和之前的最大和 哪个更大取哪个)。

 如果越到比最小值还小的。重新初始化最大值 最小值 .让他等于当前值。继续往下遍历。

	public int myMax(List<Integer> data){
		List<Integer> dataSum=new ArrayList<Integer>();
		for(int i=0;i<data.size();i++){


			if(i==0){
				dataSum.add(0, data.get(i));
			}else{
				dataSum.add(i, data.get(i)+ dataSum.get(i-1));
			}
		}
		int returnData=Integer.MIN_VALUE;
		int nowMinData=Integer.MIN_VALUE;
		int nowMaxData=Integer.MIN_VALUE;
		for(int i=0;i<dataSum.size();i++){
			if(i==0){
				returnData=nowMinData=nowMaxData=dataSum.get(0);
			}else{
				int nowData=dataSum.get(i);
				if(nowData>nowMaxData){
					nowMaxData=nowData;
					int nowreturnData=nowMaxData-nowMinData;
					returnData=Math.max(nowreturnData, returnData);
				}else if(nowData<nowMinData){
					 nowMinData=nowData;
					 nowMaxData=nowData;
				}
			}
		}
		return returnData;
	}


代码如上 小小的测试了一下 貌似是可以的。 比较难测试。 不知道有没有问题。 于是去看了答案 大神写的立马自惭形愧。。

	public int max(List<Integer> data){
		int sum=0;
		int b=0;
		for(int i=0; i<data.size(); i++)
		{
			if(b<0)
				b=data.get(i);
			else
				b+=data.get(i);
			if(sum<b)
				sum=b;
			}
		return sum;
	}

翻译成java了 好简洁。其实想一想 核心思路是一样的。只不过我没有转过来弯。用了一个数组辅助。 每当出现一次 b<0  测试的时候发现了 我的有点bug

returnData=nowMinData=nowMaxData=dataSum.get(0);//这里这样不行。因为第一个数 不是最小的 最小的应该是0和第一个数之间的最小值。

returnData=nowMaxData=dataSum.get(0);

nowMinData=Math.min(0, dataSum.get(0))

好了 其实 大神的想法就是 当一段数组的和 已经小于0了 这段数组就没有价值了。当然 在遍历这段数组的时候。 最大的和已经记录下来了。 这段和已经小于0 就抛弃 从下一段开始。 核心思想跟我的想法差不多。 只是我没有智能一步一步的想。 没有想那没远。 多了一次循环。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值