名企笔试:美团2016招聘笔试(奇数位丢弃)

来源:互联网 发布:淘宝生意参谋竞争情报 编辑:程序博客网 时间:2024/04/24 21:55

美团2016招聘笔试(奇数位丢弃)

题目描述
对于一个由0…n的所有数按升序组成的序列,我们要进行一些筛选,每次我们取当前所有数字中从小到大的第奇数位个的数,并将其丢弃。重复这一过程直到最后剩下一个数。请求出最后剩下的数字。
输入描述:
每组数据一行一个数字,为题目中的n(n小于等于1000)。
输出描述:
一行输出最后剩下的数字。
输入例子:
500
输出例子:
255
题目分析:
我们先来模拟一下这个题目的过程,看能不能从中找到一个数学公式:例如n = 9。
0 1 2 3 4 5 6 7 8 9 (10)
第一次操作:1 3 5 7 9 (5)
第二次操作:3 7 (2)
第三次操作:7 (1)
方法一、题目数据范围n<=1000,可以开一个数组进行模拟,时间复杂度是O(nlogn)。
模拟过程,标记一个k=1,每一次被删除的数字一定是(i+1)/k % 2 == 1 && a[i] == 0,如果剩下的没被标记的数大于2,k = k *2;继续循环,最后剩下一个数,一定是(i+1)/k % 2 == 1,而且有(i+1)/k = 1 … 1。因此i = k – 1;其中k = 2 ^ floor(log(n))。
方法二、这个数字题,能不能找到一个数学公式?第一个公式,每一次数据个数减少一半,多少次能到达一个数?很显然是log(n)次(向下取整),那么那个数能够在log(n)次二分之后到达1?只能是2 ^ floor(log(n))或者2 ^ floor(log(n)) -1。又因为我们第一次已经将所有的偶数划去,一次这个数一定是2 ^ floor(log(n))-1。公式法的时候,注意特殊处理一下n=1的情况。
Code:

#include<iostream>#include<stdio.h>#include<string.h>#include<math.h>#include<algorithm>using namespace std;const int MAXN = 1005;int a[MAXN];int test1(int n){//模拟的代码    memset(a,0,sizeof(a));    int k = 1;    while(true){        int cnt = 0;        for(int i=0;i<=n;i++){            if((i+1)/k % 2 == 1 && a[i] == 0){                a[i] = 1;            }            if(a[i] == 0) cnt++;            //cout<<i<<" "<<a[i]<<endl;        }//      cout<<cnt<<endl;        //这是已经剩下一个值,没有被处理。        if(cnt == 1) break;        if(cnt>1){//还有两个以上的数,继续迭代            k *= 2;        }        cnt = 0;    }    /**    for(int i=0;i<=n;i++){        cout<<i<<" ";    }    cout<<endl;    for(int i=0;i<=n;i++){        cout<<a[i]<<" ";    }    cout<<endl;    **/    int value = 1;    for(int i=0;i<=n;i++){        if(a[i] == 0) {value = i;break;}    }    cout<<2*k-1<<endl;//这里就是n的位置    return value;}int main(){    int n;    while(cin>>n){        cout<<test1(n)<<endl;           cout<<(int)pow(2,floor(log2(n)))-1<<endl;    }       return 0;}

PS:小喵分析的名企笔试面试题,请各位批评指正。

阅读全文
0 0
原创粉丝点击