2021-07-19:给定一个正数N,比如N = 13,在纸上把所有数都列出来如下: 1 2 3 4 5 6 7 8 9 10 11 12 13,可以数出1这个字符出现了6次,给定一个正数N,如果把1~N都列出来,返回1这个字符出现的多少次。

福大大 答案2021-07-19:

1.最高位是1的情况。
1364:3651364,千位上是365个1,百位上有100个1,十位上有100个1,个位上有100个1。
2.最高位不是1的情况。
5364:365
5364,千位上是1000个1,百位上有500个1,十位上有500个1,个位上有500个1。

代码用golang编写。代码如下:

package main

import (
    "fmt"
    "math"
)

func main() {
    num := 21
    ret := solution2(num)
    fmt.Println(ret)
}

// 1 ~ num 这个范围上,画了几道1
func solution2(num int) int {
    if num < 1 {
        return 0
    }
    // num -> 13625
    // len = 5位数
    len2 := getLenOfNum(num)
    if len2 == 1 {
        return 1
    }
    // num  13625
    // tmp1 10000
    //
    // num  7872328738273
    // tmp1 1000000000000
    tmp1 := powerBaseOf10(len2 - 1)
    // num最高位 num / tmp1
    first := num / tmp1
    // 最高1 N % tmp1 + 1
    // 最高位first tmp1
    firstOneNum := twoSelectOne(first == 1, num%tmp1+1, tmp1)
    // 除去最高位之外,剩下1的数量
    // 最高位1 10(k-2次方) * (k-1) * 1
    // 最高位first 10(k-2次方) * (k-1) * first
    otherOneNum := first * (len2 - 1) * (tmp1 / 10)
    return firstOneNum + otherOneNum + solution2(num%tmp1)
}

func getLenOfNum(num int) int {
    len2 := 0
    for num != 0 {
        len2++
        num /= 10
    }
    return len2
}

func powerBaseOf10(base int) int {
    return int(math.Pow10(base))
}

func twoSelectOne(c bool, a int, b int) int {
    if c {
        return a
    } else {
        return b
    }
}

执行结果如下:
图片


左神java代码