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
经典的二分查找问题。这里新添加两段比较好的代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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\n",res); 37 } 38 return 0; 39 }
这里对上述代码做一个样例跟踪演示:
假设目标t=10048.序列如下:
上图描述的是目标t=10048时,上述程序执行过程中二分查找函数里面L与R的变化过程。
下面是另一个代码,跟上述的思路基本一致。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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 }
假设目标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\n",a[0]); continue;} 18 else if(a[n-1]<t) { printf("%d\n",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\n",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\n",a[begin]); 44 else if(x>y) printf("%d\n",a[end]); 45 else printf("%d\n",(a[begin]<a[end]?a[begin]:a[end])); 46 } 47 } 48 free(a); 49 return 0; 50 }
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
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\n",res); 37 } 38 return 0; 39 }