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

JavaScriptで数値が2つの平方数の和として表せるか判定する方法

平方数(完全平方数)とは?

数学において、ある自然数が別の自然数とそれ自身との積で表されるとき、その数を平方数(完全平方数)と呼びます。

例えば、9、16、81、289 はすべて平方数です。

  • 9 = 3 × 3
  • 16 = 4 × 4
  • 81 = 9 × 9
  • 289 = 17 × 17

問題の定義

自然数 num を引数として受け取るJavaScript関数を作成します。この関数は、次の条件を満たす2つの数 mn が存在するかどうかを判定する必要があります。

(m * m) + (n * n) = num

そのような数の組み合わせが存在すれば true を、存在しなければ false を返します。

入力が以下の場合:

const num = 389;

出力は次のようになります:

const output = true;

これは、389 = (17 × 17) + (10 × 10) と表せるためです。つまり、17² + 10² = 289 + 100 = 389 が成立します。

解法:双方向ポインタ(Two Pointer)を使ったアプローチ

この問題を効率的に解くには、双方向ポインタ(ツーポインター)テクニックが有効です。手順は以下の通りです。

  1. 左ポインタ left を 0 に、右ポインタ right を √num の切り捨て値に初期化します。
  2. left * left + right * rightnum と一致すれば true を返します。
  3. 合計が num より小さければ left を増やし、大きければ right を減らします。
  4. ポインタが交差するまで繰り返し、見つからなければ false を返します。

この方法では O(√n) の計算量で判定できるため、大きな数でも高速に処理できます。

サンプルコード

const num = 389;

const canSumSquares = (num = 2) => {
  let left = 0, right = Math.floor(Math.sqrt(num));
  while (left <= right) {
    if (left * left + right * right === num) {
      return true;
    } else if (left * left + right * right < num) {
      left++;
    } else {
      right--;
    }
  }
  return false;
};

console.log(canSumSquares(num));

実行結果

コンソールには次のように出力されます:

true

コードのポイント解説

  • Math.floor(Math.sqrt(num)):右ポインタの初期値を設定しています。√num を超える整数を二乗しても num より大きくなるため、探索範囲はこれで十分です。
  • left <= right:同じ数を2回使うケース(例:50 = 5² + 5²)にも対応できるよう、等号を含めています。
  • 計算量:ループは最大 √n 回しか回らないため、時間計算量は O(√n)、空間計算量は O(1) と非常に効率的です。

まとめ

双方向ポインタを使うことで、ある自然数が2つの平方数の和で表せるかどうかを簡潔かつ高速に判定できます。この手法は「Two Sum」系の問題にも応用できる汎用的なテクニックなので、ぜひ覚えておきましょう。

  1. JavaScriptで配列をnum個に分割!部分配列の最大合計を最小化する二分探索アルゴリズム

    問題概要負でない整数のみを含む配列 arr を第1引数に、整数 num(num < arr.length)を第2引数として受け取るJavaScript関数を作成します。関数の目的は、元の配列を空でない連続した部分配列にちょうど num 個に分割することです。その際、各部分配列の合計値の中で最大のものが最小になるように分割し、その最小化された「最大合計」を戻り値として返します。入力例const arr = [5, 1, 4, 8, 7];const num = 2;出力例const output = 15;出力の解説長さ5の配列を2つの部分配列に分割する方法は全部で4通りあります。それぞれ

  2. JavaScriptで2つの二分探索木(BST)のノード値の合計が目標値に一致するか判定する方法

    問題 JavaScriptの関数を作成します。この関数は、第1引数として1つ目の二分探索木のルートroot1を、第2引数として2つ目の二分探索木のルートroot2を受け取り、さらに第3引数として整数targetを受け取ります。 この関数は、「1つ目の木の中のあるノード」と「2つ目の木の中のあるノード」の値を足し合わせた結果がtargetと一致するようなペアが存在する場合にのみtrueを返し、存在しない場合はfalseを返す必要があります。 たとえば、次のような入力が与えられたとします。 const target = 23; 2つのBSTの例 この場合の出力は次のようになります。 const