剑指Offer-PHP实现

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

2018-08-30  本文已影响0人  懒人成长

题干

输入一个整数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);
上一篇 下一篇

猜你喜欢

热点阅读