Swift-1到n的正整数中1出现的次数

题目:1到n中正整数出现的次数,n= 2(1,2)只出现了1个“1”,n= 12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)1的个数是5.
最简单的解法就是遍历一次分别求出每个数字中包含1的个数:

func countForSingleNumber(num:Int)->Int {
    var n = num
    var count = 0
    while n > 0 {
        count += (n%10 == 1 ? 1 : 0)
        n = n/10
    }
    return count
}

var maxNumber = 109
var count = 0
for i in 1...maxNumber {
    count += countForSingleNumber(num: i)
}

关于这个题目还有其他的各种各样的解法,下面提供一种思路,比较容易简单和理解:
①设定整数点(如1,10,100,1000...)作为位置点i(n的各位、十位、百位,千位...),分别对每个数位上有多少包含1的点进行分析.
②根据设定的整数位置,对n进行分割,分为两部分,高位n/i,低位n%i,假设i表示百位:
1)假设n=84272,百位对应的数>=2,,i=100,则a=842,b=72,此时百位为1的次数有a/10+1=85(最高两位0~84),每一次都包含100个连续的点,即共有(a%10+1)100个点的百位为1
2)假设n=84172,i=100,则a=841,b=72,此时百位对应的就是1,则共有a%10(最高两位0-84)次是包含100个连续点,百位的数字补全,所以需要通过b的个数来判断(a%10
100+(b+1)
3)假设n=84072,此时a=310,b=56,此时百位为1的次数有a/10=84(最高两位0~84)
③当百位对应0或>=2时,有(a+8)/10次包含所有100个点,还有当百位为1(a%10==1),需要增加局部点b+1,之所以加8是因为当百位为0,则a/10==(a+8)/10,当百位>=2,补8会产生进位位,效果等同于(a/10+1),,当百位为1(a%10==1),需要增加局部点b+1.
最终试下代码如下:

func numOfOne(n:Int) -> Int {
    var i = 1
    var count = 0
    while i <= n {
        let a = n / i
        let b = n % i
        //余数是1
        let remain = (a%10 == 1) ? (b+1) : 0
        count = count + (a+8)/10 * i + remain
        i *= 10
    }
    return count
}

可以通过第一种方式的结果来验证第二种分析是否正确:

var maxNumber = 12
var count = 0
for i in 1...maxNumber {
    count += countForSingleNumber(num: i)
}
var simpleCount = numOfOne(n: maxNumber)
print("FlyElephant:方法1:\(count)---方法2:\(simpleCount)")

你可能感兴趣的:(Swift-1到n的正整数中1出现的次数)