您的位置:首页 > 职场人生

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

2013-04-25 11:30 295 查看
大神 地址 :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 就抛弃 从下一段开始。 核心思想跟我的想法差不多。 只是我没有智能一步一步的想。 没有想那没远。 多了一次循环。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: