JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

自然数列のn番目の数字を求めるJavaScript関数の実装方法

数学において、自然数とは1から始まり無限に続く数のことを指します。

最初の15個の自然数は以下のとおりです。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

この数列を先頭から1文字ずつ拾っていくと、1番目の数字は「1」、2番目は「2」、3番目は「3」……と続きます。ところが9を超えたあたりで挙動が変わります。10番目の数字は「10」の1桁目である「1」になり、11番目の数字はその次の「0」になるのです。

つまり本記事の課題は、数値 n を受け取り、このように並べた自然数列の n番目の数字 を見つけて返すJavaScript関数を作成することです。

コード例

const findNthDigit = (num = 1) => {
    let start = 1;
    let len = 1;
    let count = 9;
    while(num > len * count) {
        num -= len * count;
        len++; count *= 10;
        start *= 10;
    };
    start += Math.floor((num-1)/len);
    let s = String(start);
    return Number(s[(num-1) % len]);
};
console.log(findNthDigit(5));
console.log(findNthDigit(15));
console.log(findNthDigit(11));
console.log(findNthDigit(67));

出力結果

コンソールには次のように表示されます。

5
2
0
8

アルゴリズムの解説

一見すると単純な問題ですが、n が大きくなると全数列を文字列として生成して1文字ずつ数える方法では非効率です。そこでこのコードでは桁数ごとにグループ分けして考える手法を使っています。

各桁数に含まれる数字の個数

  • 1桁の数(1〜9): 9個 × 1桁 = 9文字
  • 2桁の数(10〜99): 90個 × 2桁 = 180文字
  • 3桁の数(100〜999): 900個 × 3桁 = 2700文字

変数 len(現在の桁数)、count(その桁数の数の個数)、start(その桁数の最初の数)を用意し、whileループの中で n が現在のグループの総文字数より大きい間、その文字数分だけ減算しながら次のグループへ進みます。これにより、n 番目の数字がどの桁数のグループに属するかを特定できます。

具体的な数字の特定

グループが決まったら、start += Math.floor((num-1)/len) によって、そのグループ内で何番目の数にあたるかを計算し、対象となる数そのものを求めます。最後に数値を文字列化し、(num-1) % len でその数の中の何桁目かを割り出して返しています。

たとえば findNthDigit(11) の場合、11番目の数字は「10」の2桁目なので 0 が返り、findNthDigit(67) は数列中67番目の位置にあるため 8 が返ります。このアルゴリズムなら、n が非常に大きな値でも高速に答えを求められます。

  1. JavaScriptでパスカルの三角形のn行目の要素を求める方法

    パスカルの三角形とは パスカルの三角形は、前の行の隣接する要素同士を足し合わせていくことで構成される、三角形状の数列配置です。各行の両端は必ず1となり、内側の各要素はそのすぐ上にある2つの要素の和になります。 パスカルの三角形の最初のいくつかの要素は以下の通りです。 求めるもの 今回は、正の整数 num を唯一の引数として受け取り、パスカルの三角形の num 行目に存在するすべての要素を配列として返すJavaScript関数を作成します。 たとえば、入力が次の場合: const num = 9; 期待される出力は以下のようになります。 const output = [1, 9, 36, 8

  2. 【JavaScript】パドヴァン数列のn番目の要素を求める方法

    パドヴァン数列とはパドヴァン数列(Padovan Sequence)とは、次の初期値で定義される整数列 P(n) のことです。P(0) = P(1) = P(2) = 1そして、以下の漸化式に従って各項が決まります。P(n) = P(n-2) + P(n-3)この漸化式から導かれる最初のいくつかの値は次のとおりです。1, 1, 1, 2, 2, 3, 4, 5, 7, 9, 12, 16, 21, 28, 37, 49, 65, 86, 114, 151, 200, 265, …フィボナッチ数列が直前の2項の和で定義されるのに対し、パドヴァン数列は「2つ前」と「3つ前」の項を足す点が特徴的です