微软100题第3题:求子数组的最大和
2015-06-26 16:23
381 查看
题目:输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
分析:该题也是Leetcode上面的题目,第53题。解题方法有多种, 本次用两种时间复杂度最低的方式实现。
方法1:动态规划O
,分析题目后,最大的连续子序列和从以当前元素pData[i]结尾的序列和中找,当前元素结尾的序列和为f(i).
f(i)= pData[i], i=0 or f(i-1)<=0; or f(i) = f(i-1)+pData[i], i!=0 and f(i-1)>0
取 MAX(f(i)), i>=0 and i<n;
int maxSubArray( vector<int> & nums ){
int cursum=0, maxsum=nums[0];
for( vector<int>::size_type i=0; i!= nums.size(); i++ )
{
cursum += nums[i];
if( cursum > maxsum )
{
maxsum = cursum;
}
if(cursum <0)
cursum = 0;
}
return maxsum ;
}
方法2:使用“分而治之”策略,O[NlogN]。最大连续子序列和最可能出现在序列的3个地方, 只需取三个数据中最大的那个即可。
a. 数组的左半边;
b. 数组的右半边;
c. 跨越左右,中间的某一段区间。
前两种情况采用递归即可处理。
static int MaxSubSum( vector<int> & nums , int left, int right){
int mid=(left +right)/2, maxleft=0, maxright=0;
int leftsum=0, rightsum=0;
int maximum =0;
if(left == right)
{
//if(nums[left] >0)
return nums[left] ;
}
maxleft = MaxSubSum(nums, left, mid);
maxright = MaxSubSum(nums, mid+1, right);
if(maxleft>maxright)
maximum = maxleft;
else
maximum = maxright;
maxleft = nums[mid];
maxright = nums[mid+1];
for(int i=mid; i>=left; i--)
{
leftsum += nums[i];
if(leftsum > maxleft)
maxleft = leftsum;
}
for(int i= mid+1; i<=right; i++)
{
rightsum += nums[i];
if(rightsum > maxright)
maxright = rightsum;
}
return maximum = ((maxleft + maxright) > maximum)?(maxleft + maxright) : maximum;
}
int maxSubArray( vector<int> & nums )
{
return MaxSubSum(nums, 0, nums.size()-1);
}
相关文章推荐
- 微软无线镭射简报鲨8000激光笔记本鼠标 - (2)
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- 对《大家都在点赞 Windows Terminal,我决定给你泼一盆冷水》一文的商榷
- 微软镜像下载
- 微软公布2013年必应搜索十大首页美图
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 微软Word 2007数学插件 Microsoft Math 提供下载
- C#数据结构与算法揭秘二
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 巧用微软EWF来保护系统
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法