您的位置:首页 > 其它

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

2017-06-01 23:34 218 查看

美团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:小喵分析的名企笔试面试题,请各位批评指正。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: