1.在黑板上写下50个数字:1至50。在接下来的49轮操作中,每次做如下动作:选取两个黑板上的数字a和b,擦去,在黑板上写|b - a|。请问最后一次动作之后剩下数字可能是什么?为什么?
解:1-49之间所有奇数。
1)先证明最后剩下数一定为奇数。
1+2+...+50=1275为奇数。如果每次减去2个奇数或2个偶数,然后加上它们的差,注意到差一定为偶数,所以一次动作之后剩下数的和仍然为奇数。如果每次减去1个奇数和1个偶数,然后加上它们的差,注意到差一定为奇数,所以一次动作之后剩下数的和仍然为奇数。总之每次动作之后剩下数的和一定为奇数,这就证明了最后剩下数一定为奇数。
2)再给出一种产生所有奇数的取法。
对于1-49之间的任意奇数n,先保留1和(n+1),然后2-n和(n+2)-50相邻两两取出,这样一共可以得到24个1,24个1两两取出得到0,最后只剩下之前保留的1和(n+1),(n+1)-1=n就得到n了。
例如n=25,先保留1和26,然后2-25和27-50两两相邻取出,这样一共可以得到24个1,24个1两两取出得到0,最后只剩下之前保留的1和26,26-1=25就得到25了。
2.已知三个升序整数数组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]|)
请设计一求最小三元组距离的最优算法,并分析时间复杂度。
解:
在数轴上,三个点两两距离之和等于最大值与最小值距离的两倍。
1.算法一
#include<iostream>
#include<climits>
using namespace std;
#define l 3
#define m 4
#define n 5
int main()
{
int a[l]={1,2,3};
int b[m]={4,5,6,7};
int c[n]={8,9,10,11,12};
int max(int a,int b,int c);
int min(int a,int b,int c);
int min_distance(int a[],int b[],int c[]);
cout<<min_distance(a,b,c)<<endl;
return 0;
}
int max(int a,int b,int c)
{
int temp=a>b?a:b;
temp=c>temp?c:temp;
return temp;
}
int min(int a,int b,int c)
{
int temp=a<b?a:b;
temp=c<temp?c:temp;
return temp;
}
int min_distance(int a[],int b[],int c[])
{
int i=0,j=0,k=0,maxP,minP,min_dis=INT_MAX;
while(i<l&&j<m&&k<n)
{
maxP=max(a[i],b[j],c[k]);
minP=min(a[i],b[j],c[k]);
min_dis=(maxP-minP)<min_dis?(maxP-minP):min_dis;
if(minP==a[i])i++;
else if(minP==b[j])j++;
else k++;
}
return min_dis;
}
2.算法二
#include<iostream>
#include<cmath>
using namespace std;
#define l 3
#define m 4
#define n 5
int main()
{
int a[l]={1,2,3};
int b[m]={4,5,6,7};
int c[n]={8,9,10,11,12};
int min(int a,int b,int c);
int min_distance(int a[],int b[],int c[]);
cout<<min_distance(a,b,c)<<endl;
return 0;
}
int min(int a,int b,int c)
{
int temp=a<b?a:b;
temp=c<temp?c:temp;
return temp;
}
int min_distance(int a[],int b[],int c[])
{
int i=0,j=0,k=0,sum,temp;
int min_sum=(abs(a[i]-b[j])+abs(a[i]-c[k])+abs(b[j]-c[k]))/2;
for(int p=0;p<l+m+n;p++)
{
sum=(abs(a[i]-b[j])+abs(a[i]-c[k])+abs(b[j]-c[k]))/2;
min_sum=sum<min_sum?sum:min_sum;
temp=min(a[i],b[j],c[k]);
if(temp==a[i])
{
if(++i>=l)break;
}
if(temp==b[j])
{
if(++j>m)break;
}
if(temp==c[k])
{
if(++k>n)break;
}
}
return min_sum;
}