01:查找最接近的元素

http://noi.openjudge.cn/ch0111/01/

01:查找最接近的元素

总时间限制: 1000ms 内存限制: 65536kB
描述

在一个非降序列中,查找与给定值最接近的元素。

输入
第一行包含一个整数n,为非降序列长度。1 <= n <= 100000。
第二行包含n个整数,为非降序列各元素。所有元素的大小均在0-1,000,000,000之间。
第三行包含一个整数m,为要询问的给定值个数。1 <= m <= 10000。
接下来m行,每行一个整数,为要询问最接近元素的给定值。所有给定值的大小均在0-1,000,000,000之间。
输出
m行,每行一个整数,为最接近相应给定值的元素值,保持输入顺序。若有多个值满足条件,输出最小的一个。
样例输入
3
2 5 8
2
10
5
样例输出
8
5

经典的二分查找问题。这里新添加两段比较好的代码:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<math.h>
 4 int fun(int a[],int n,int t)
 5 {
 6     int L,R,mid;
 7     int x,y;
 8     L=0;R=n-1;
 9     while(L<=R)
10     {
11         mid=L+(R-L)/2;
12         if(a[mid]==t) return a[mid];
13         else if(a[mid]<t) L=mid+1;
14         else R=mid-1;
15     }
16     x=abs(a[L]-t);
17     y=abs(a[R]-t);
18     if(x<y) return a[L];
19     else if(x>y) return a[R];
20     else return (a[L]<a[R]?a[L]:a[R]);
21 }
22 int main(int argc, char *argv[])
23 {
24     int n,a[100003],m,t,i,res;
25     scanf("%d",&n);
26     for(i=0;i<n;i++) scanf("%d",&a[i]);
27     scanf("%d",&m);
28     for(i=0;i<m;i++)
29     {
30         scanf("%d",&t);
31         
32         if(t<a[0]) res=a[0];
33         else if(t>a[n-1]) res=a[n-1];
34         else res=fun(a,n,t);
35         
36         printf("%d
",res);
37     }
38     return 0;
39 }
View Code

这里对上述代码做一个样例跟踪演示:

假设目标t=10048.序列如下:

上图描述的是目标t=10048时,上述程序执行过程中二分查找函数里面L与R的变化过程。

下面是另一个代码,跟上述的思路基本一致。

 1 //来自ttps://blog.csdn.net/qq_33837704/article/details/80314377
 2 #include<iostream>
 3 #include<string.h>
 4 using namespace std;
 5 int n,m,target;
 6 int base,top,mid=0;
 7 long long nums[100010];
 8 int main(){
 9     memset(nums,-1,sizeof(nums));
10     cin>>n;
11     for(int i=0;i<n;i++){
12         cin>>nums[i];
13     }
14     cin>>m;
15     while(m--){
16         cin>>target;
17         base=0;
18         top=n-1;
19         while(base<=top){
20             mid=(base+top)/2;
21             if(nums[mid]==target){
22                 break;;
23             }else if(nums[mid]<target){
24                 base=mid+1;
25             }else {
26                 top=mid-1;
27             }
28         }
29         if(nums[mid]==target){
30             cout<<target<<endl;
31         }else{
32             if(base>=n||base<0){
33                 cout<<nums[top]<<endl;
34             }else if(top>=n||top<0){
35                 cout<<nums[base]<<endl;
36             }else{
37                 if(abs(nums[base]-target)>abs(nums[top]-target)){
38                     cout<<nums[top]<<endl;
39                 }else{
40                     if(abs(nums[base]-target)<abs(nums[top]-target)){
41                         cout<<nums[base]<<endl;
42                     }else{
43                         if(base<top){
44                             cout<<nums[base]<<endl;
45                         }else{
46                             cout<<nums[top]<<endl;
47                         }
48                     }
49                 }
50             }
51         }
52     }
53 }
View Code

 假设目标t=10092,那么二分过程如下:

 假设目标t=10006,那么二分查找过程如下:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 int main(int argc, char *argv[])
 4 {
 5     int n,i,*a,m,t;
 6     int begin,end,mid;
 7     int x,y;
 8     
 9     scanf("%d",&n);
10     a=(int *)malloc(n*sizeof(int));
11     for(i=0;i<n;i++) scanf("%d",&a[i]);
12     
13     scanf("%d",&m);
14     for(i=0;i<m;i++)
15     {
16         scanf("%d",&t);
17         if(a[0]>t) { printf("%d
",a[0]); continue;}
18         else if(a[n-1]<t) { printf("%d
",a[n-1]); continue;}
19         
20         begin=0;
21         end=n-1;
22         mid=(begin+end)/2;
23         while(begin<=end)   //while(end-begin>1)
24         {
25             if(a[mid]==t) { printf("%d
",a[mid]);break;}
26             else 
27             {
28                 if(a[mid]>t)
29                 {
30                     end=mid-1;
31                 }
32                 else 
33                 {
34                     begin=mid+1;
35                 }
36             }
37             mid=(begin+end)/2;
38         }
39         if(a[mid]!=t)
40         {
41             x=abs(a[begin]-t);
42             y=abs(a[end]-t);
43             if(x<y) printf("%d
",a[begin]);
44             else if(x>y) printf("%d
",a[end]);
45             else printf("%d
",(a[begin]<a[end]?a[begin]:a[end]));
46         }
47     }
48     free(a);
49     return 0;
50 }
 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<math.h>
 4 int fun(int a[],int n,int t)
 5 {
 6     int L,R,mid;
 7     int x,y;
 8     L=0;R=n-1;
 9     while(L<=R)
10     {
11         mid=L+(R-L)/2;
12         if(a[mid]==t) return a[mid];
13         else if(a[mid]<t) L=mid+1;
14         else R=mid-1;
15     }
16     x=abs(a[L]-t);
17     y=abs(a[R]-t);
18     if(x<y) return a[L];
19     else if(x>y) return a[R];
20     else return (a[L]<a[R]?a[L]:a[R]);
21 }
22 int main(int argc, char *argv[])
23 {
24     int n,a[100003],m,t,i,res;
25     scanf("%d",&n);
26     for(i=0;i<n;i++) scanf("%d",&a[i]);
27     scanf("%d",&m);
28     for(i=0;i<m;i++)
29     {
30         scanf("%d",&t);
31         if(n==1) res=a[0]; //这个重要 
32         else if(t<a[0]) res=a[0];//这个重要
33         else if(t>a[n-1]) res=a[n-1];//这个重要
34         else res=fun(a,n,t);
35         
36         printf("%d
",res);
37     }
38     return 0;
39 }
View Code
原文地址:https://www.cnblogs.com/huashanqingzhu/p/6882821.html