在升序数组中查找和等于给定值的两个数

来源:互联网 发布:unity3d 5.x下载 编辑:程序博客网 时间:2024/05/16 14:23

【题  目】输入一个已经按升序排列的数组,一个给定的数字,在数组中查找两个数,使得它们的和等于给定的数字。要求时间复杂度为O(n),如果存在多对满足条件的数字对,只给出一对即可。例如:输入数组『1,2,4,7,11,15』,给定一个数字15,那么输出应该为『4,11』.

 

【思路1】我们先不考虑时间复杂度为O(n),按照最直观的思路来考虑,容易想到,我们一次固定数组中的一个数字,然后遍历这个数字之后的各个数字,判断和是否为给定的和,这样的时间复杂度为O(n2)。容易写出如下的代码:

复制代码
 1 #include<iostream> 2 #include<string> 3 using namespace std; 4  5 bool FindTwoNumbers(int array[],int length,int sum,int &num1,int &num2) 6 { 7     if(array == NULL || length < 2) 8         return false; 9 10     for(int i = 0;i < length - 1;++i)11     {12         for(int j = i + 1;j < length;++j)13         {14             if(array[i] + array[j] == sum)15             {16                 num1 = array[i];17                 num2 = array[j];18                 return true;19             }20         }21     }22 23     return false;24 }25 26 int main()27 {28     cout<<"Enter the length of your array:"<<endl;29     int arraylength = 0;30     cin>>arraylength;31     int *p = new int[arraylength];32 33     cout<<"Enter the numbers in your array:"<<endl;34     for(int i = 0;i < arraylength;++i)35     {36         cin>>p[i];37     }38 39     cout<<"Enter a sum you want to find:"<<endl;40     int result = 0;41     cin>>result;42     43     int a = 0;44     int b = 0;45     FindTwoNumbers(p,arraylength,result,a,b);46 47     cout<<"the two numbers are:"48         <<"\t"<<a<<"\t"<<b<<endl;49     50     delete[] p;51     return 0;52 }
复制代码

运行结果如下:

 

【思路2】上面的算法时间复杂度为O(n2),但是这个算法有一个好处就是,对于不排序的数组也是能够适用的,因为我们采用的方法是遍历,对于排序不排序,我们并不关心。这也从一个侧面说明了上面的算法时间复杂度较高的原因是:我们并没有充分利用数组是按升序排列的这个条件。如果考虑这个条件,我们会怎么做?

  我们考虑一种特殊的情况,数组是严格的等差数列,那么给定一个和,如果能够找到一对整数满足题条件,那么根据等差数列的性质,较大的数想左移动一个数字,叫小的数向有移动一个数字,就又找到了另一对满足条件的数对。那么对于一般情况,我们能否这样考虑:首先判断第一个数字和最后一个数字的和,如果这个和大于给定的和,那么就让最后一个数字左移;反之,如果它们的和小于给定的和,就让第一个数字右移,这样是合乎逻辑的,然而这个算法容易使人产生一个疑问,会不会漏掉呢?这需要严格的数学证明,笔者暂时还不能给出证明,待日后补充,也希望数学很牛的同学不吝赐教。该思路代码如下:

复制代码
 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 bool FindTwoNumbers(int array[],int length,int sum,int &num1,int &num2) 5 { 6     //无效输入,返回false 7     if(array == NULL || length < 2) 8         return false; 9 10     int *start = &array[0];11     int *end = &array[length -1];12 13     while(start < end)14     {15         if((*start + *end) == sum)16         {17             num1 = *start;18             num2 = *end;19             return true;20         }21         22         //小于给定和,较小的数右移23         else if((*start + *end) < sum)24         {25             start++;26         }27         28         //大于给定和,较大的数左移29         else if((*start + *end) > sum)30         {31             end--;32         }33     }34 35     return false;36 }37 38 39 int main()40 {41     cout<<"Enter the length of your array:"<<endl;42     int arraylength = 0;43     cin>>arraylength;44     int *p = new int[arraylength];45 46     cout<<"Enter the numbers in your array:"<<endl;47     for(int i = 0;i < arraylength;++i)48     {49         cin>>p[i];50     }51 52     cout<<"Enter a sum you want to find:"<<endl;53     int result = 0;54     cin>>result;55     56     int a = 0;57     int b = 0;58     FindTwoNumbers(p,arraylength,result,a,b);59 60     cout<<"the two numbers are:"61         <<"\t"<<a<<"\t"<<b<<endl;62     63     delete[] p;64     return 0;65 }
复制代码

运行结果如下:

 

 


References:

程序员面试题精选100题:http://zhedahht.blog.163.com/blog/static/2541117420072143251809/

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

原创粉丝点击