阿里巴巴笔试题

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;
}

时间复杂度都为O(l+m+n)。

附录:

只证max,min同理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值