Создавать массив длиной в N может быть «дорого» – займёт память. Поэтому для метода «в лоб» предложу простой цикл с циклом для поиска «1» в каждом кандидате:
const sumone = n => {
let sum = 0;
for (let i=n; i>0; i--) {
const numstr = i.toString(10);
for (let j=0, len = numstr.length; j<len; j++)
if (numstr[j] == '1') sum++;
}
return sum;
}
Но можно подумать над формулой вычисления без перебора. Или частично сократить перебор. Например, для чисел, состоящих из одних «9» искомое число единиц в ряде вычисляется как функция числа цифр:
d * 10^(d-1)
Вот так:
9 .. 1 = 1 * 10^0
99 .. 20 = 2 * 10^1
999 .. 300 = 3 * 10^2
9999 .. 4000 = 4 * 10^3
99999 .. 50000 = 5 * 10^4
Например, для числа
12345
можно мгновенно получить сумму для 9999 и начать перебирать с 10000 до 12345. Это тоже можно упростить: отбросим первую единицу, она есть каждый раз, и остаётся то же, что от 0000 до 2345 + 2346 единиц.
0..2345
в свою очередь опять сокращается: сразу известно 0..999, остаётся от 1000 до 2345.
1000 .. 1999 опять упрощаем отбрасыванием первой единицы: на 999 приходится 300 единиц плюс 1000 первых единиц. Остаётся 2000 .. 2345. Тут можно отбросить двойку и посчитать только 0..345. Снова уходит 0..99. и т.д
Надо будет ещё подумать над формулой..