前天晚上顺手做了一下阿里的在线笔试题,还是挺难的,要是现在的水平去校招,估计得跪。
最近有些忙,今天才有时间整理一下之前写的第二题代码。
第二道题目是菜鸟仓库的货架格子编号问题,题目的意思是货架可以按下面的方式进行编号,求从头数下来第k个货物编号是多少?
输出样例:k=5,那么对应第三行第二列,也就是2。k=14,对应第五行第四个,输出4。
我们需要注意的是,从第十行开始,10是分别变成了1和0,11分别是1和1。
也就是说k=55时,输出应该是1,不是10。
1
1 2
1 2 3
1 2 3 4
1 2 3 4 5
1 2 3 4 5 6
1 2 3 4 5 6 7
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1 0
1 2 3 4 5 6 7 8 9 1 0 1 1
最简单的思路,把矩阵都打出来,一个个数,当然,这不现实....
其实题目直接可以分成两个子问题,找行:h,和,找列:r。
就像样例中“k=14,对应第h=5行,第r=4个,输出4。”
很多人会觉得10分成了1和0,100分成了1,0和0三个,就不能直接找了。
其实只是略复杂了一点而已。
我们从找列这个问题举例:
如果r很大,前面会有1~9排列的一位数,会有10~99排列的两位数......
那么一位数在货架上占用的位置的总个数就是1*(9-1+1)=1*9,两位数占用总个数是2*(99-10+1)=2*90,三位数占了3*(999-100+1)=3*900
数字规律非常明显。
这样,我们不难算出r对应的是几位数,并且是第几个,也就能得出答案。
我直接贴具体的代码吧:
int find_r(int r){
int digit=1; //位数
int digit_sum=9; //digit位数下的总个数
int temp, num, rem, base, loca;
//num用于锁定数字是digit位数的第几个
//rem用于后面计算数字中的具体哪一位
for(;r>digit*digit_sum;digit++,digit_sum*=10){
r-=digit*digit_sum;
}
num=ceil((float)r/digit);
rem=r%digit;
//计算小于digit位的最大数
base=0;
temp=digit;
while(temp>1){
base=base*10+9;
temp--;
}
//loca计算所求位置对应的未分裂的数字
loca=base+num;
int ans;
if(rem!=0)
rem=digit-rem;
while(rem>=0){
ans=loca%10;
loca=loca/10;
rem--;
}
return ans;
}
输出:
10
1
11
0
14
1
15
2
190
1
191
0
192
0
关于求行数h,其实也是同样的思路,数字都是有规律的,把公式列出来就不难思考,不上代码了。
大家有什么不同的思路交流一下呀~~