找出满足条件的数


1、找出数组中满足条件的两个数,如数组a={12,4,10,19,3,55,38,40,77,8},输入59,则打印4+55=59,19+40=59。

方法很简单,先对数组排序,时间复杂度为O(nlogn),然后用两个指针分别指向数组的首位和末尾,将首末两数相加和为S,如果S等于给定的数SUM则记录,如果S>SUM则尾指针减一,如果S<SUM则首指针加一,直到首指针大于等于尾指针。总的时间复杂度为O(nlogn)+O(n)=O(nlogn),代码如下:


int FindNumsSum(int arr[], int n, int sum, int recd[10][2])
{
	bool flag=false;
	if(arr==NULL || n<1 || recd==NULL)
		return 0;
	InsertSort(arr,n);
	for(int k=0;k<n;k++)
	{
		printf("%d ",arr[k]);
	}
	printf("\n");
	int i=0,j=n-1;
	int m=0;
	while(i<j)
	{
		if(arr[i]+arr[j]==sum)
		{
			recd[m][0]=arr[i];
			recd[m][1]=arr[j];
			m++;
			i++;
			flag=true;
		}
		else if(arr[i]+arr[j]<sum)
		{
			i++;
		}
		else
		{
			j--;
		}
	}
	if(flag)
		return m;
	return 0;
}

这里补充两点。

一:同上,对于无序数组,时间复杂度为O(nlogn),代码如下:

typedef struct PAIR
{
	int n1[10];
	int n2[10];
	int count;
}Pair;
PAIR findnum(int *s,int n,int sum)//找出两个数,使得a+b=sum,有序为O(n),无序为O(nlogn)
{
	PAIR ar;
	int i=0;
	for(i=0;i<10;i++)
	{
		ar.n1[i]=0;
		ar.n2[i]=0;
		ar.count=0;
	}
	int *begin=s;     
	int *end=s+n-1;        
	i=0;
	while(begin<end)        
	{     
		if(*begin+*end>sum)     
			end--;          
		else if(*begin+*end<sum)      
			begin++;      
		else       
		{
			ar.n1[i]=*begin;
			ar.n2[i]=*end;
			i++;       
			ar.count=i;
			begin++;
			end--;
		}
	}
	return ar;
}

二:如果都是正整数,对于无序数组,可以在O(n)时间内,实现。具体方法为:首先可以剔除数组中比给定的sum大的数,然后定义一个table[20]={0}(这里的20就是sum),从左往右扫描原数组,如数组为a[6]={6,10,7,2,14,18};

1. 当table[a[i]]==0,则记录table[sum-a[i]]==1,如table[20-6]=1,table[20-10]=1...;

2. 当table[a[i]]==1时,如table[a[4]]==1(即table[14]),则说明前面已经出现了了sum-a[i],即20-14=6,此时记录a[i]与sum-a[i]即可。具体代码如下:

typedef struct PAIR
{
	int n1[10];
	int n2[10];
	int count;
}Pair;
PAIR findnum2(int *s, int n, int sum) //对于都是正整数的情况,用hashtable法,有序无序都是O(n)
{
	int htab[100]={0};
	//memset(htab,0,sizeof(int)*50);
	PAIR ar;
	int i=0;
	for(i=0;i<10;i++)
	{
		ar.n1[i]=0;
		ar.n2[i]=0;
		ar.count=0;
	}
	for(i=0;i<n;i++)
	{
		if(htab[sum-s[i]]==0)
			htab[sum-s[i]]=1;
		if(htab[s[i]]==1)
		{
			ar.n1[ar.count]=s[i];
			ar.n2[ar.count]=sum-s[i];
			ar.count++;
		}
	}
	return ar;
}

注:该方法只适用于都是正整数的情况,时间复杂度为O(n),方法有待完善。

2、输出所有和为整数S的连续正数序列,如输入15 ,则1+2+3+4+5=4+5+6=7+8=15,输出(1,2,3,4,5),(4,5,6),(7,8)

有了上述的思想,该题目也可以利用首尾数字的移动来实现。

比如输入数字s=15:

(1)令a0=1,a1=2;

(2)判断a0+a1==s? ,如果a0+a1<s则a1向后加1,即a1++,如果a0+a1>s,则a0向后加1,并舍去a0前面的数字,知道a1>=(s+1)/2,具体步骤如下:

 1+2<15

1+2+3<15

1+2+3+4<15

1+2+3+4+5==15 找到第一组

1+2+3+4+5+6>15

2+3+4+5+6>15

3+4+5+6>15

4+5+6==15 找到第二组

4+5+6+7>15

5+6+7>15

6+7<15

6+7+8>15

7+8==15 找到第三组,退出

实现代码如下:

void PrintResults(int a, int b)
{
	if(a>=b)
		return;
	for(int i=a;i<=b;i++)
	{
		printf("%d, ",i);
	}
	printf("\n");
}
void FindContinuousSequence(int sum)
{
	if(sum<3)
		return;
	int a0=1;
	int a1=2;
	int mid=(1+sum)/2;
	int tmpsum=a0+a1;
	while(a0<mid)
	{
		if(tmpsum==sum)
		{
			PrintResults(a0,a1);
		}
		while(tmpsum>sum && a0<mid)
		{
			tmpsum-=a0;
			a0++;
			if(tmpsum==sum)
			{
				PrintResults(a0,a1);
			}
		}
		a1++;
		tmpsum+=a1;
	}
}  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值