看大神文章小结——微软面试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 更新最大值 更新 最大的和(判断当前的最大和和之前的最大和 哪个更大取哪个)。
如果越到比最小值还小的。重新初始化最大值 最小值 .让他等于当前值。继续往下遍历。
代码如上 小小的测试了一下 貌似是可以的。 比较难测试。 不知道有没有问题。 于是去看了答案 大神写的立马自惭形愧。。
翻译成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 就抛弃 从下一段开始。 核心思想跟我的想法差不多。 只是我没有智能一步一步的想。 没有想那没远。 多了一次循环。
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 就抛弃 从下一段开始。 核心思想跟我的想法差不多。 只是我没有智能一步一步的想。 没有想那没远。 多了一次循环。
相关文章推荐
- 看大神文章小结——微软面试5,6
- 看大神文章小结——微软等面试 35,36,37,38
- 看大神文章小结——微软等面试12,13,14
- 看大神文章小结——微软等面试 31,32,33,34
- 看大神文章小结——微软等面试7,8
- 看大神文章小结——微软等面试 18,19
- 看大神文章小结——微软等面试 27,28,29,30
- 看大神文章小结——微软面试4
- 看大神文章小结——微软等面试 39,40
- 看大神文章小结——微软面试2
- 看大神文章小结——微软等面试 20,21
- 看大神文章小结——微软等面试 23,24,25,26
- 看大神文章小结——微软面试1
- 看大神文章小结——微软等面试10,11
- 看大神文章小结——微软等面试 41-45
- 看大神文章小结——微软等面试 16,17
- 微软面试小结
- 关于精选微软等公司数据结构+算法面试100题的文章
- Const用法小结 [ C/C++ const], 好文章。const值得仔细推敲。对付面试很有用的
- 微软面试100题系列---最大二维子矩阵和