今天看到一道题:统计1到400亿之间的自然数中含有多少个1?
第一感觉是挺简单的,于是有了如下代码,毕竟挺相信计算机的性能.
console.time(1);
let x = 0;
function js(item){
for (let i=1;i<=item;i++) {
let s = i.toString();
if(s.indexOf("1")!=-1){
x++;
}
}
}
js(40000000);
console.timeEnd(1);
console.log(x)
思路就是,将数字转换为字符串,查找字符串中有没有1,看似没有什么问题,运行一下,实际没结果,看了一下,计算4000万花了大概4.5秒,如果成正比400亿需要4500秒;显然太久太久.
我觉得事情不是如此简单,于是有了如下代码
console.time(1);
// 首位是1
// ss = (ss - 1) * 9 + 1 + (Math.pow(10, xy));
// 首位不是1
// ss = (ss - 1) * (x.toString()[0]-1) + (Math.pow(10, xy));
function isone(x) {
let allnum = 0;
let numlist = [];
for (let i in x.toString()) {
numlist.push(x.toString()[i] * Math.pow(10, (x.toString().length - i - 1)))
}
function yes(num) {
let xy = 1;
let ss = 2;
for (let i = num + 1; i > 2; i--) {
if (i != 3) {
ss = (ss - 1) * 9 + 1 + (Math.pow(10, xy));
xy++;
} else {
ss = (ss - 1) * (x.toString()[0] - 1) + (Math.pow(10, xy));
xy++;
}
}
return ss;
}
function no(num) {
let xy = 1;
let ss = 2;
for (let i = num; i > 2; i--) {
ss = (ss - 1) * 9 + 1 + (Math.pow(10, xy));
xy++;
}
return ss;
}
for (let i in numlist) {
let num = numlist[i].toString().length;
if ( numlist[i].toString().length > 2) {
if ( numlist[i].toString()[0] != "1") {
allnum += yes(num);
} else {
allnum += no(num)
}
} else {
let x=0
for (let y=1;y<=numlist[i];y++) {
let s = y.toString();
if(s.indexOf("1")!=-1){
x++;
}
}
allnum += x;
}
}
return allnum;
}
console.log(isone(54884884894));;
console.timeEnd(1);
可以计算任意数字 如 54884884894
看了下运算时间,只有5ms,快了90万倍,
这大概就是算法的魅力吧.