《剑指Offer》-43.1~n整数中1出现的次数

题干

输入一个整数n,求1~n这n个整数的十进制表示中1出现的次数。例如,输入12,1~12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。

解题思路

举例分析,例如数字21345,可以将1~21345分成两段,1~1345和1346~21345。

先看1346~21345中1出现的次数。分为两种情况,先分析1出现在最高位的情况,在1346~21345中1出现在10000~19999这10000个数字的万位中,一共出现了10000次。而对于最高位是1的情况下,1出现的次数就是剩余位数的数字+1次。

除去最高位之外的4位数中,1出现的次数可以通过排列组合计算,等于最高位的数字*(剩余位数) * 10^(剩余位数-1)

对于1~1345中1出现的次数可以通过递归的方式计算。

代码实现

<?php
function numberOf1Between1AndN($n)
{
    if ($n <= 0) {
        return 0;
    }

    return numberOf1($n);
}

function numberOf1($n)
{
    if (empty($n) || !is_numeric($n)) {
        return 0;
    }

    $n = (string)$n;

    $first = $n[0];
    $len = strlen($n);
    if ($len == 1 && $first == 0) {
        return 0;
    }
    if ($len == 1 && $first > 0) {
        return 1;
    }

    $numFirstDigit = 0;
    if ($first > 1) {
        $numFirstDigit = pow(10, $len - 1);
    } elseif ($first == 1) {
        $numFirstDigit = intval(substr($n, 1)) + 1;
    }
    $numOtherDigits = $first * ($len - 1) * pow(10, $len - 2);
    $numRecursive = numberOf1(substr($n, 1));

    return $numFirstDigit + $numOtherDigits + $numRecursive;
}

echo numberOf1Between1AndN(999);
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天的题目是如果人生是本书,你希望后面是什么样子... 原来命题作文也没有那么无聊,至少这个题目还是有很多想像空间...
    简珺阅读 1,202评论 1 1
  • 今天画的是路飞,不知道为什么,感觉比昨天的乔巴好画一些…… 还是老规矩,先上图镇楼!!! 1.线稿啦~画的时候注...
    懵橙阅读 6,955评论 0 3