1001 数组中和等于K的数对 (51nod)

Posted lklk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1001 数组中和等于K的数对 (51nod)相关的知识,希望对你有一定的参考价值。

基准时间限制:1 秒 空间限制:131072 KB 分值: 5 难度:1级算法题
技术分享图片 收藏
技术分享图片 关注
给出一个整数K和一个无序数组A,A的元素为N个互不相同的整数,找出数组A中所有和等于K的数对。例如K = 8,数组A:{-1,6,5,3,4,2,9,0,8},所有和等于8的数对包括(-1,9),(0,8),(2,6),(3,5)。
 
Input
第1行:用空格隔开的2个数,K N,N为A数组的长度。(2 <= N <= 50000,-10^9 <= K <= 10^9)
第2 - N + 1行:A数组的N个元素。(-10^9 <= A[i] <= 10^9) 
Output
第1 - M行:每行2个数,要求较小的数在前面,并且这M个数对按照较小的数升序排列。
如果不存在任何一组解则输出:No Solution。
Input示例
8 9
-1
6
5
3
4
2
9
0
8
Output示例
-1 9
0 8
2 6
3 5



刚开始写的时候以为只是个简单的排完序然后逐个查找看是否有满足条件的即可,,,,没想到交了几发,居然超时了,,soga,原来时间复杂度到了O(n^2)...
在查找方面需要优化,下面附上超时代码和AC代码,,然后去网上找了找,居然用到了lower_bound这个函数,
超时代码
#include<bits/stdc++.h>
using namespace std;
int num[50001];
int main()
{
    int k,n;
    cin>>k>>n;
    for(int i=0;i<n;i++)
    cin>>num[i];
    sort(num,num+n);
    int flag=0;
    for(int i=0;i<n;i++)
    {
      for(int j=n-1;j>i;j--)
      {
          if(num[i]+num[j]==k)
          {
              cout<<num[i]<<" "<<num[j]<<endl;
              flag=1;
          }
          
          
       } 
        
    }
    if(flag==0)
    cout<<"No Solution"<<endl;
    return 0;
}

AC代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int num[50001];
 4 int main()
 5 {
 6     int k,n;
 7     cin>>k>>n;
 8     for(int i=0;i<n;i++)
 9     cin>>num[i];
10     sort(num,num+n);
11     int flag=0;
12   int i=0;
13   int t=n-1;
14   int sum;
15   while(i<t)
16   {
17       sum=num[i]+num[t];
18       if(sum==k)
19       {
20               printf("%d %d\n",num[i++],num[t--]);
21               flag=1;
22       }
23       
24     else if(sum<k)
25     i++;
26     else
27     t--;
28 
29   }
30     if(flag==0)
31     cout<<"No Solution"<<endl;
32     return 0;
33 }

lower_bound解法

#include "iostream"  
#include <algorithm>  
#define N 50006  
using namespace std;  
  
long long num[N];  
  
int main()  
{  
    long long k, n;  
    bool flag = true;  
    cin >> k >> n;  
    for (int i = 0; i < n; i++)  
    {  
        cin >> num[i];  
    }  
  
    sort(num, num + n);  
    for (int i = 0; i < n; i++)  
    {  
        int pos = lower_bound(num, num + n, k - num[i]) - num;  
        if (num[i] + num[pos] == k && pos > i)  
        {  
            cout << num[i] << " " << num[pos] << endl;  
            flag = false;  
        }  
          
    }  
    if (flag)  
    {  
        cout << "No Solution" << endl;  
    }  
  
    getchar();  
    getchar();  
    return 0;  
}  

借此机会,了解了lower_bound函数的一些用法

该函数为C++ STL内的函数

其包含在头文件#include <algorithm> 中

注意事项

调用lower_bound之前必须确定序列为有序序列,否则调用出错

函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置

举例如下:

一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标

pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。

pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。

pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。

所以,要记住:函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!~

返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置














以上是关于1001 数组中和等于K的数对 (51nod)的主要内容,如果未能解决你的问题,请参考以下文章

51 nod 1001 数组中和等于K的数对

51nod 1001 数组中和等于K的数对二分查找/排序

[51nod]1001 数组中和等于K的数对

51nod 1001 数组中和等于k的数对

51Nod 1001 数组中和等于K的数对

51Nod - 1001 数组中和等于K的数对 (排序+ 尺取)