朋友面试遇到一个上升数的问题,据说网上没有答案,我也没有查。写了一个小方法,没有做BUG处理,大佬们勿喷。
上题: [请问1到10000之前,有多少升数字? ]
升数字就是从左向右读,数值是依 次上升的即可,比如123, 1256,1389,但是1123, 165就不是。
看到这个题的第一眼首先想到通过for循环来解答,但是这并不是考官要的结果,而且数字区间越大则程序的执行时间越长,故在分析阶段就放弃了这种思路。
我现在的解题思路:
(1):由于为上升数,所以1~10000中 最大的数字为6789,最小数字他这里没有说明白 不知道12,13这种数字算不算,如果不算的话 取值区间则缩小为 123~6789 ,就算是算的话0012~6789 ,此时将筛选掉3000+个数字,即使依然采用上述for循环的话 也会少运行将近1/3次。数字越大筛选掉的数字就越多,比如1~100000,最大数字是56789,筛选掉了4W+个数字。
(2):此时程序运行效率已经提高了将近一半,但是依然有很多无用的循环,其实在一个符合要求的数字的十位数确定的时候,我们就已经知道个位数有几种情况了,所以没必要去循环个位数,只需要将十位数自增1,然后运算,这样我们只循环十位数,效率是普通for循环的1/10。
function Epistasis(i){
if(arr[i]==(10-(length-i))){
if(i!=0){
Epistasis(i-1)
}else{
return ;
}
}else{
count+=(9-arr[length-2])
arr[i]+=1;
for (var j = i+1; j <=length-2; j++) {
arr[j]=arr[j-1]+1;
};
Epistasis(length-2)
}
}
(3):如何确定数字符合要求,在初始化的时候将数字分成数组,比如我们的题目是1~10000,如果12是符合要求的第一个数的话,那么初始化得到的数组就是arr=[0,0,1,2],然后每次循环十位数。下边是确定第一个符合的数字代码:
//构造想要的结果如0012
for (var i = 0; i <length; i++) {
if(i==length-2){
arr.push(1)
}else if(i==length-1){
arr.push(2)
}else{
arr.push(0)
}
};
然后问题就解决了。下边是我全部代码:
//十位+1
function Epistasis(i){
if(arr[i]==(10-(length-i))){
if(i!=0){
Epistasis(i-1)
}else{
return ;
}
}else{
count+=(9-arr[length-2])
arr[i]+=1;
for (var j = i+1; j <=length-2; j++) {
arr[j]=arr[j-1]+1;
};
Epistasis(length-2)
}
}
var length=9;
var arr=[];
var count=1;
//构造想要的结果如0012
for (var i = 0; i <length; i++) {
if(i==length-2){
arr.push(1)
}else if(i==length-1){
arr.push(2)
}else{
arr.push(0)
}
};
console.time("Epistasis");
Epistasis(length-2)
console.log(count)
console.timeEnd("Epistasis");
目前代码为1.0版本,没有做BUG处理,有BUG求轻喷,有更好的解答方法请小伙伴分享一下,PS:本人没有找百度,如果百度有更好的解答,请把链接甩我,多谢。
注:
- 本文版权归原作者所有,仅用于学习与交流;
- 如需转载,烦请按下方注明出处信息,谢谢!朋友面试遇到的上升数问题的解答