题目:
已知三个升序整数数组a[l], b[m]和c[n]。请在三个数组中各找一个元素,是的组成的三元组距离最小。三元组的距离定义是:假设a[i]、b[j]和c[k]是一个三元组,那么距离为:
Distance = max(|a[ I ] – b[ j ]|, |a[ I ] – c[ k ]|, |b[ j ] – c[ k ]|)
请设计一个求最小三元组距离的最优算法,并分析时间复杂度。
PS:这道题考研前找工作的同学问过我,结果就出现在408真题上了(QAQ)
思路:根据三元组定义,显然三个数字最接近时,得到的距离最小。不妨假设a【i】<=b【j】<=c【k】。
分三种情况:
1)第一种移动a【i】,若有a【i】<=b【j】<=c【k】或者b【j】<=a【i】<=c【k】,此时最小距离更新;若移动后的a【i】>=c【k】,此时最短距离不变或者刷新。
2)第二种移动b【j】,若有a【i】<=b【j】<=c【k】之间,则最短距离不变;若移动后的b【j】>=c【k】,则最短距离不变。————这种做法不可能刷新最小距离,不可取。
3)第三种移动c【k】,显然不可取。
综上,只有移动最小元素时(第一种),才可能会刷新最小距离。当某一个数组遍历完成时,便会得到最小三元组距离。时间复杂度O(l+m+n)。
我们把问题升级一下,如何求符合条件的所有三元组并输出最小三元组距离 ?
开三个容器分别存储对应三元组,若当前的三元组距离小于之前的,则clear清空容器并把当前三元组push对应容器;若当前的三元组距离等于之前的,则把该组三元组push对应容器。
code:
#include<bits/stdc++.h>
using namespace std;
const int maxn=10010;
const int inf=0x7fffffff;
int a[maxn],b[maxn],c[maxn];
int main(){
int m,n,l;
cin>>m>>n>>l;
for(int i=0;i<m;i++) cin>>a[i];
for(int i=0;i<n;i++) cin>>b[i];
for(int i=0;i<l;i++) cin>>c[i];
int i=0,j=0,k=0;
vector<int>v1,v2,v3;//保存三元组序列
int dis=inf;
while(1){
if(i==m || j==n || k==l) break;
int temp=abs(a[i]-b[j])+abs(a[i]-c[k])+abs(b[j]-c[k]);
if(temp<dis){
dis=temp;
v1.clear();v1.push_back(a[i]);
v2.clear();v2.push_back(b[j]);
v3.clear();v3.push_back(c[k]);
}else if(temp==dis){
v1.push_back(a[i]);
v2.push_back(b[j]);
v3.push_back(c[k]);
}
if(a[i]<=b[j] && a[i]<=c[k]) i++;
else if(b[j]<a[i] && b[j]<c[k]) j++;
else k++;
}
cout<<dis<<endl;
for(int i=0;i<v1.size();i++){
cout<<v1[i]<<" "<<v2[i]<<" "<<v3[i]<<endl;
}
return 0;
}
End!