比較無聊的一天,小明決定列舉了一大堆石頭。他先數了數石頭,發現堆裏有幾塊石頭,而後到商店去買標籤。每個標籤都是從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; } }