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

注意数组元素可正可负,给定值设为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;
}


     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值