剑指offer - 整数中1出现的次数:使用数学归纳法解题

根据题目描述可知,此题要求的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为底

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

posted @ 2019-10-28 15:25  AloeAndClover  阅读(197)  评论(0编辑  收藏  举报