比较无聊的一天,小明决定列举了一大堆石头。他先数了数石头,发现堆里有几块石头,而后到商店去买标签。每个标签都是从0到9的数字,每个石头都应该分配一个惟一的数字,从1到N。若是每一个标签的成本是1美圆,小明会花多少钱在这个项目上?算法
function rocks(int $n): int { return ; }
其中:code
$n为石头数,且$n为大于1的正整数
返回为须要的成本
例子:io
小明发现了13块石头: 则石头上的数字为: 1,2,3,4,5,6,7,8,9,10,11,12,13 所须要的标签为: 1,2,3,4,5,6,7,8,9,1,0,1,1,1,2,1,3 所须要的成本为: 17
这道题对于咱们来说,不少人的固定思路就是如下这种function
function rocks(a) { var str = ''; for(var i=1; i<=a; i++){ str += i; } return str.length; } rocks(13);
经过求长度的方式来解决这类问题,可是若是说数据量一大,就会形成溢出。因此咱们要改进一下算法。
如下是我对这道题的理解:
经过题意得知,若是是1位数的,就是1张标签,若是是两位数的就是两个标签,若是是三位数的就是三个标签。
咱们只须要循环他所传递的长度的次数就能够了,经过,等差数列的方式,求出次数,
好比:
1位数: 10-1 * 1
2位数: 1010 - 101 * 2
3位数: 101010 - 10 10 2
如下是个人代码:循环
function rocks(int $n): int { // 获得长度. $length = strlen($n); $count = 0; if($length > 1){ // 循环长度-1次. 这里求的是位数 for($i=1;$i<$length;++$i){ $count += $i * (pow(10,$i)-pow(10,$i-1)); } // 若是到了 最后一次即到了 10的i次方 直接用n来减去便可 $count += ($n - pow(10,$i-1) + 1)*$i; return $count; }else{ return $n; } }