为学论坛“每日一题”系列---最长连续子数组

给定一个整数数组,返回它其中最长的连续整数数列长度。

例如 a[] = {100,4,200,1,3,2} 因为其中包含1,2,3,4所以返回4.


原题链接:http://www.51weixue.com/thread-518-1-1.html


我的做法:

1、第一次遍历输出数组,获取必要信息,构造正整数A数组,负整数B数组。

2、第二次遍历正整数B数组,求出正整数中最长的长度的子数组,并记录包含0的子数组的长度,以便计算跨越正负区间的子数组长度。

3、第三次遍历负整数C数组,求出负整数中最长的长度的子数组,并记录包含-1的子数组的长度,以便计算跨越正负区间的子数组长度。

4、比较并得出最长连续子数组的长度。


时间复杂度:O(3n),空间复杂度:O(3n)。


代码如下:

#include<stdio.h>
#include<memory.h>

const int N = 1000 ;

int LongestSubArrary(int *ptrA,int n) ;
inline int max(int x, int y) ;

int main(void)
{
	int A[N] ;
	int i,n,t ;	
	
	freopen("in.txt","r",stdin) ;
	scanf("%d",&t) ;

	while(t-- > 0)
	{
		scanf("%d",&n) ;

		for(i = 0 ; i < n ; ++i)
		{
			scanf("%d",&A[i]) ;
		}
		printf("%d\n",LongestSubArrary(A,n)) ;
	}
	return 0 ;
}


int LongestSubArrary(int *ptrA,int n)
{
	int B[N],C[N] ;
	int i,nLongestLen,nBeg,nEnd,nZeroLen ;
	int fFirst ,fStart,fCalc ;
	int nNegaLongestLen,nNegaBeg,nNegaEnd,nNegaZeroLen ;
	int fNegaFirst ;
	int nLen ;
	int nMegaLen = 0 ;

	memset(B,0,sizeof(B)) ;
	memset(C,0,sizeof(C)) ;

	nBeg = 1 ;
	nEnd = 0 ;

	nNegaBeg = -1 ;
	nNegaEnd = -2 ;	

	fFirst = 0 ;
	fNegaFirst  = 0 ;
	for(i = 0 ; i < n ; ++i)
	{
		if(ptrA[i] >= 0) //正数和0
		{
			if(0 == fFirst)
			{
				nBeg = ptrA[i] ;
				nEnd = ptrA[i] ;
				fFirst = 1 ;
			}
			else if(nBeg > ptrA[i])
			{
				nBeg = ptrA[i] ;
			}
			else if(ptrA[i] > nEnd)
			{
				nEnd = ptrA[i] ;	
			}
			B[ptrA[i]] = 1 ;
		}
		else			//负数
		{
			if(0 == fNegaFirst)
			{
				nNegaBeg = ptrA[i] ;
				nNegaEnd = ptrA[i] ;
				fNegaFirst = 1 ; 
			}
			else if(nNegaBeg > ptrA[i])
			{
				nNegaBeg = ptrA[i] ;
			}
			else if(ptrA[i] > nNegaEnd)
			{
				nNegaEnd = ptrA[i] ;	
			}
			C[-ptrA[i]] = 1 ;
		}
	}

	/******************正数******************/
	fStart = 0 ;
	nLongestLen = 0 ;
	nLen = 0 ;
	nZeroLen = 0 ;
	fCalc = 0 ;
	for(i = nBeg ; i <= nEnd+1 ; ++i)
	{
		if(1 == B[i])
		{
			nLen++ ;
			fStart = 1 ;
		}
		else if(0 == B[i] && 1 == fStart)
		{
			if(nLen > nLongestLen)
			{
				nLongestLen = nLen ;
				if(0 == nBeg && 0 == fCalc)
				{
					nZeroLen = nLen ;
					fCalc = 1 ;
				}
			}
			nLen = 0 ;
			fStart = 0 ;
		}
	}
	/**************************/

	/*******************负数*****************/
	fStart = 0 ;
	nNegaLongestLen = 0 ;
	nLen = 0 ;
	nNegaZeroLen = 0 ;
	fCalc = 0 ;
	for(i = nNegaBeg ; i <= nNegaEnd+1 ; ++i)
	{
		if(1 == C[-i])
		{
			nLen++ ;
			fStart = 1 ;
		}
		else if(0 == C[-i] && 1 == fStart)
		{
			if(nLen > nNegaLongestLen)
			{
				nNegaLongestLen = nLen ;
				if(-1 == nNegaEnd && 0 == fCalc)
				{
					nNegaZeroLen = nLen ;
					fCalc = 1 ;
				}
			}
			nLen = 0 ;
			fStart = 0 ;
		}
	}
	/****************************************/
	if(-1 == nNegaEnd && 0 == nBeg)
	{
		nMegaLen = nZeroLen + nNegaZeroLen ;	
	}
	return max(max(nLongestLen,nNegaLongestLen),nMegaLen) ;
}

int max(int x, int y)
{
	return x > y ? x : y ;
}

测试数据:

7
5
5 0 3 -1 1
7
-1 -5 1 -2 0 2 3
11
-1 0 1 2 3 5 6 7 8 9 10
10
-4 -3 -2  5 6 7 2 1 -1 4
4
-1 0 -2 2
3
0 1 2
3
-1 -3 -5










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值