您的位置:首页 > 其它

未排序数组中累加和为给定值的最长子数组

2016-01-17 15:36 204 查看
注意数组元素可正可负,给定值设为k,求其和为K的最长子数组长度

解法1:

最笨的方法,穷举所有子数组,每次穷举到特定子数组时候,把子数组元素都加起来,设立length,然后维持该length,时间复杂度O(N^3)

解法2:

使用前缀和数组,比如数组a[10],设置help数组,help[i]代表a[0]+a[1]+```+a[i],这样,在穷举到某个特定数组时候,假设该区间左端为i,右端为j,则不用再麻烦的去累加,直接计算help[j]-help[i]-1就可以啦 时间复杂度为O(n^2)

解法3:

根据第二种解法,我们可以考虑使用hash表,怎么用呢?

首先我们可以把穷举子数组(O(n^2)复杂度)简化,比如对于元素a[i],我们可以找以a[i]为结尾的最长子数组,找以a[i+1]为结尾的最长子数组, 比较n次,就可以找到啦。

其次,我们如何找以a[i]为结尾的最长子数组呢,最笨的办法好像还是从头开始,穷举,a[0]````a[i] a[1]````a[i] a[2]`````a[i],这样看来好像和方法2没什么多大的进步,但是其实这个过程是可以用O(1)解决的,怎么解决,那就是哈希表喽

我们先遍历一个元素时候,会得出一个值sum,这个值得含义是从a【0】加到该元素,我们先设想有该元素,然后我们可以知道,哦哦,既然加到现在是sum,那么如果后面某一段值为k,前一段值为sum-k,并且我们知道了sum-k的长度,我们岂不可以得知和为k这一段的长度啦?于是乎我们就找,在哈希表中是否有key为sum-k,值为index下标的元素,如果有,那证明大功告成,因为哈希表中存储key,肯定代表是“从左边开始第一次加到key”,而不会是再加5,再加-5这样的又变成key这样的情况,这样,既然我们保证了加到sum-k的区间长度最短,就可以保障后面和为k的区间长度最长,维持一个len变量就可以了。

#include<iostream>
#include <hash_map>
#include <algorithm>
using namespace std;
//给定一个无序数组,并给定k值,找出其中最长的和等于k的子数组,输出其长度 注意,数组元素可正可负
//要求空间复杂度为O(n),时间复杂度为O(n)
int a[]={1,2,3,3};
int k=6;
int findArray(int len)
{
int ret=0;
int i,sum=0;
hash_map<int,int> mymap;
mymap[0]=-1;
for(i=0;i<len;i++)
{
sum+=a[i];
if(mymap.find(sum-k)!=mymap.end())
{
ret=max(ret,i-mymap.find(sum-k)->second);
}
else
{
mymap[sum]=i;
}
}
return ret;

}

int main()
{
cout<<findArray(4)<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: