剑指offer

根据题目描述可知,此题要求的1是由[1,n]之间所有数的位数为1的个数

测试用例:10,112,226

112

个位:[1][11,21,...,111]

1 + 11*1

十位:[10,11,...,19][110,...,112]

10 + 3

百位:[100,...,112][]

13

226

[1][11,21,...,221]

1 + 22*1

[10,11,...,19][110,...119,210,...219]

10 + 2*10

[100,...,199][]

100

10

[1][]

1

[10][]

1

根据以上例子,得到规律,代码实现如下:

private static int solution2(int n) {
     int count = 0;
    for (int i = 1; i <= n; i *= 10) {
      // 位前半部分计算
      int bitLess = n / i > 1 ? i : (n % i + 1);
      // 位后半部分计算
      int bitMore = 0;
      if (n / (i * 10) > 0) {
        if (n % (i * 10) >= (2 * i - 1)) {
          bitMore = n / (i * 10) * i;
        } else {
          bitMore = (n / (i * 10) - 1) * i;
          if (n % (i * 10) > 0) bitMore += n % i + 1;
        }
      }
      count += bitLess + bitMore;
    }
    return count;
  }

小结:

该解法的时间复杂度为O(logN),这里的对数是10为底

较之寻常解法的时间复杂度,优化了不少

原文地址:https://www.cnblogs.com/ihaokun/p/11751270.html