JavaScriptで残りの数の合計が2つの数の積に等しくなるペアを見つける方法
問題の概要
1から任意の整数 num までの連続した数列を考えます。この中から2つの数(それぞれ m と n と呼びます)を選び、次の条件を満たす組み合わせを見つけます。
sum(1 to num) - (m + n) = m * n
つまり、「選んだ2つの数を除いた残りの数の合計」が「選んだ2つの数の積」と等しくなるようなペアです。最終的に、条件を満たすすべての組み合わせを配列として返します。
具体例
入力が次の場合を考えてみましょう。
const num = 10;
このときの出力は次のようになります。
const output = [
[7, 6]
];理由はシンプルで、1から10までの合計が 55 であり、
55 - (6 + 7) = 6 * 7 = 42
という等式が成立するためです。つまり、6 と 7 を取り除いた残りの数の合計(42)が、6 × 7 の積(42)と一致します。
実装コード
この問題は次のように解くことができます。
const num = 10;
const pickNumbers = num => {
const sum = (num) * (num + 1) * (.5);
const results = [];
for (let n = 1; n <= num; n++) {
let first = sum - n;
let second = n + 1;
if (first % second === 0) {
let m = first / second;
if (m < num && m !== n && results.every(group => group[0] + group[1] !== m + n)){
results.push([m, n]);
}
}
}
return results;
}
console.log(pickNumbers(10));コードの解説
このアルゴリズムのポイントは以下の3点です。
- 合計の高速な計算: 等差数列の和の公式
n(n+1)/2を利用することで、1からnumまでの合計をループなし(O(1))で求めています。 - m を一意に導出する変形: 条件式 sum − (m + n) = m × n を
mについて解くと、m = (sum − n) / (n + 1)となります。これにより、nを1つ決めれば対応するmがすぐに計算でき、全ペアを総当たりする必要がなくなります。 - 妥当性チェック:
mが整数であること(first % second === 0)、num未満であること、nと異なること、さらに同じペアの重複登録を防ぐ確認を行ったうえで、結果に追加しています。
実行結果
コンソールには次のように出力されます。
[
[7, 6]
]すべてのペアを二重ループで調べる O(num²) のアプローチと比べ、この方法はループが1回で済むため、大きな num に対しても効率的に動作します。数式を事前に変形しておくことで探索範囲を大きく絞れる、数学的な工夫が活きた良い例といえるでしょう。
-
【JavaScript】整数の中からn番目の回文数を見つける方法
問題 数値 n を引数として受け取り、0から数えて n 番目にあたる回文数(回文となる整数)を返す JavaScript 関数を作成します。 たとえば、1番目の回文数は「0」、2番目は「1」、10番目は「9」です。「10」は逆から読むと「01」となり回文ではないため、11番目の回文数は「11」となります。 回文数とは 回文数とは、桁を逆から並べ替えても元の数と同じになる整数のことです。「7」「121」「1331」などがその例です。 解決策:コード例 以下が実際のコードです。 const num = 31; const findNthPalindrome = (num = 1) => {
-
JavaScriptで増加する三角形のn行目の全数値の合計を求める方法
増加する三角形とはこの問題における「増加する三角形」とは、次のような形の三角形を指します。 1 2 3 4 5 67 8 9 10ご覧のとおり、各行には連続する自然数が左から右へと順に配置され、行が下に進むほど要素の数が1つずつ増えていきます。問題の概要数値 n を受け取り、増加する三角形の n 行目に含まれるすべての数値の合計を返すJavaScript関数を作成する必要があります。例えば15行目の場合、その行には105から120までの連続する15個の数値が含まれており、それらの合計は1695