每日一題:一 石頭 ----- 這裏注重算法和效率

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