Bootstrap

xtu oj Distance

文章目录

回顾

代码

#include<stdio.h>
#define N 100010
int a[N],b[N];

void sort(int q[],int l,int r){//快速排序模板
	if(l>=r){
		return;
	}
	int i=l-1,j=r+1,x=q[(l+r)/2];
	while(i<j){
		do{
			i++;
		}while(q[i]<x);
		do{
			j--;
		}while(q[j]>x);
		if(i<j){
			int temp=q[i];
			q[i]=q[j];
			q[j]=temp;
		}
	}
	sort(q,l,j);
	sort(q,j+1,r);
}

int myabs(int x){//绝对值函数
	if(x<0){
		return -x;
	}
	return x;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);//输入
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=0;i<m;i++){
			scanf("%d",&b[i]);
		}
		sort(a,0,n-1);//排序
		sort(b,0,m-1);
		
		int ans=1e9+10;
		int i=0,j=0;//双指针
		while(i<n&&j<m){
			if(myabs(a[i]-b[j])<ans){//更新答案
				ans=myabs(a[i]-b[j]);
			}
			
			if(a[i]<b[j]){//这里是关键哈哈,就是我们想要两个数字的差距尽可能小,那就需要 a 里面小的元素尽可能接近 b 里面大的元素
				i++;//最小的答案是 0 ,假设 a 里面的元素更大,那需要一个更大的 b  来试图找到一个更优的答案,这样两个元素才可能更加
			}else{//接近
				j++;
			}
		}
		
		printf("%d\n",ans);
	}
	
	return 0;
}

思路

再写一题就去复习服务端。

这个题有点像曼哈顿距离,曼哈顿距离是 |x1-x2|+|y1-y2| ,这个是 |x-y|

求这个最小的距离,我感觉就是用最小的元素去比较一下就好了,最小的元素和最大的元素,首先排序一下,然后计算最大的元素和最大的元素,最小的元素和最小的元素,最大的元素和最小的元素,也就是说有效的元素最多就是四个元素,a,b 两个数组的最大值和最小值,感觉是这样子,写一下试试。

#include<stdio.h>
#define N 100010
int a[N],b[N];

void sort(int q[],int l,int r){//快速排序模板
	if(l>=r){
		return;
	}
	int i=l-1,j=r+1,x=q[(l+r)/2];
	while(i<j){
		do{
			i++;
		}while(q[i]<x);
		do{
			j--;
		}while(q[j]>x);
		if(i<j){
			int temp=q[i];
			q[i]=q[j];
			q[j]=temp;
		}
	}
	sort(q,l,j);
	sort(q,j+1,r);
}

int myabs(int x){//绝对值函数
	if(x<0){
		return -x;
	}
	return x;
}

int mymin(int x,int y){//求最小值
	if(x<y){
		return x;
	}
	return y;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);//输入
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=0;i<m;i++){
			scanf("%d",&b[i]);
		}
		sort(a,0,n-1);//排序
		sort(b,0,m-1);
		
		int ans1=myabs(a[0]-b[0]),ans2=myabs(a[0]-b[m-1]),ans3=myabs(a[n-1]-b[0]),ans4=myabs(a[n-1]-b[m-1]);
		int temp1=mymin(ans1,ans2);//求最小值
		int temp2=mymin(ans3,ans4);
		int ans=mymin(temp1,temp2);
		
		printf("%d\n",ans);
	}
	
	return 0;
}

为啥直接 WA 了呢。

嗷嗷,我知道了,就是答案不一定是在端点的地方,数组中间可能有元素更加接近。用双指针找一下最优的答案就好。可能最难想到的就是啥时候更新指针,两个元素越接近,答案就越优,所以假设 a 里面的元素小于 b 里面的元素,就用更大的 a 的元素,这样就能得到更优的答案。

最近从朋友那里学了 qsort 那里的 cmp 指针啥的是啥意思,现在把快排的模板换掉,试着写一下,考试的时候确实用封装好的函数会爽一些。

#include<stdio.h>
#include<stdlib.h>
#define N 100010
int a[N],b[N];

int cmp(const void *a,const void *b){
	return (*(int*)a-*(int*)b);
}

int myabs(int x){//绝对值函数
	if(x<0){
		return -x;
	}
	return x;
}

int main(){
	int t;
	scanf("%d",&t);
	while(t--){
		int n,m;
		scanf("%d%d",&n,&m);//输入
		for(int i=0;i<n;i++){
			scanf("%d",&a[i]);
		}
		for(int i=0;i<m;i++){
			scanf("%d",&b[i]);
		}
		qsort(a,n,sizeof(a[0]),cmp);//排序
		qsort(b,m,sizeof(b[0]),cmp);
		
		int ans=1e9+10;
		int i=0,j=0;//双指针
		while(i<n&&j<m){
			if(myabs(a[i]-b[j])<ans){//更新答案
				ans=myabs(a[i]-b[j]);
			}
			
			if(a[i]<b[j]){//这里是关键哈哈,就是我们想要两个数字的差距尽可能小,那就需要 a 里面小的元素尽可能接近 b 里面大的元素
				i++;//最小的答案是 0 ,假设 a 里面的元素更大,那需要一个更大的 b  来试图找到一个更优的答案,这样两个元素才可能更加
			}else{//接近
				j++;
			}
		}
		
		printf("%d\n",ans);
	}
	
	return 0;
}

qsortstdlib.h 这个头文件里面,四个参数按照上面代码里面写就好了,第一个参数是数组,第二个参数是数组长度,第三个参数是一个元素的大小,第四个参数是比较函数,比较函数需要按照上面的格式写,因为底层函数定义的时候是这样定义的。

比较函数的返回值的时候,第一个 * 表示的意思是解引用,解引用就是取某地址的元素的值,第二个 * 表示的是强制转换指针类型,把空指针转换成 int 类型的指针。

感觉考试一定会考排序,所以读者一定要学会快速排序模板或者 qsort 函数的使用,因为冒泡排序的时间复杂度是平方的,可能在用的时候超时,快速排序的时间复杂度是 O(nlogn) ,一般是可以接受的。

;