寻找和为定值的两个数
2014-07-24 15:49
309 查看
题目:输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数
字。
要求时间复杂度是 O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组 1、2、4、7、11、15 和数字 15。由于 4+11=15,因此输出 4 和 11。
分析:
1、最简答的方法就是穷举法,挨个计算比较,时间复杂度为O(N^2)
2、每一次要查找的时间都要花费为 O(N),这样下来,最终找到两个数还是需要 O(N^2)的复杂度。利用二分查找,可以将 O(N)的查找时间提高到O(log2N)
3、双指针扫描法
两个指针 i,j,各自指向数组的首尾两端, 令i=0, j=n-1, 然后i++, j--,逐次判断a[i]+a[j]?=sum, 如果某一刻a[i]+a[j]>sum,则要想办法让 sum 的值减小,所以此刻 i 不动,j--,如果某一刻 a[i]+a[j]<sum,则要想办法让 sum 的值增大,所以此刻 i++,j 不动。时间复杂度为O(N)
字。
要求时间复杂度是 O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组 1、2、4、7、11、15 和数字 15。由于 4+11=15,因此输出 4 和 11。
分析:
1、最简答的方法就是穷举法,挨个计算比较,时间复杂度为O(N^2)
2、每一次要查找的时间都要花费为 O(N),这样下来,最终找到两个数还是需要 O(N^2)的复杂度。利用二分查找,可以将 O(N)的查找时间提高到O(log2N)
3、双指针扫描法
两个指针 i,j,各自指向数组的首尾两端, 令i=0, j=n-1, 然后i++, j--,逐次判断a[i]+a[j]?=sum, 如果某一刻a[i]+a[j]>sum,则要想办法让 sum 的值减小,所以此刻 i 不动,j--,如果某一刻 a[i]+a[j]<sum,则要想办法让 sum 的值增大,所以此刻 i++,j 不动。时间复杂度为O(N)
//输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。 //要求时间复杂度是 O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。 //例如输入数组 1、2、4、7、11、15 和数字 15。由于 4+11=15,因此输出 4 和 11 #include <iostream> using namespace std; //直接穷举法 void find1(int a[],int n,int sum) { for(int i=0;i<n;i++) { for(int j=i+1;j<n;j++) { if(a[i]+a[j]==sum) { cout<<a[i]<<'+'<<a[j]<<'='<<a[i]+a[j]<<endl; return; } } } } //头尾双指针扫描法 O(n) void find2(int a[],int n,int sum) { int f=0,b=n-1; while(f<b) { if(a[f]+a[b]<sum) f++; else if(a[f]+a[b]>sum) b--; else { cout<<a[f]<<'+'<<a[b]<<'='<<a[f]+a[b]<<endl; return; } } } //二分查找法 O(nlog2n) int search(int a[], int n, int v) { int f=0,b=n-1; int mid=f+(b-f)/2; while(f<b) { mid=f+(b-f)/2; if(a[mid]==v) return mid; else if(a[mid]<v) f=mid+1; else b=mid-1; } return -1; } void find3(int a[],int n,int sum) { for(int i=0;i<n;i++) { int v=sum-a[i]; int j=search(a,n,v);//二分查找加快速度 if(j>0) { cout<<a[i]<<'+'<<a[j]<<'='<<a[i]+a[j]<<endl; return; } } } void main() { int a[]={1,2,4,7,11,15}; int n=sizeof(a)/sizeof(int); find1(a,n,15); find2(a,n,15); find3(a,n,15); system("pause"); }