JavaScriptでmからnに到達するための最小操作回数を求めるアルゴリズム
問題
2つの数値 m と n を引数として受け取るJavaScript関数を作成します。関数は、m の状態から開始して n に到達するまでに必要な最小の操作回数を求めて返します。
使用できる操作は、次の2つだけです。
- 2倍(Double) – 表示中の数値を2倍する
- デクリメント(Decrement) – 表示中の数値から1を引く
たとえば、次のように関数を呼び出した場合を考えてみましょう。
const m = 5;
const n = 8;
この場合の出力は次のようになります。
const output = 2;
出力の解説
m = 5 から n = 8 へは、次の手順で2回の操作で到達できます。
5 → 4 → 8
まず「デクリメント」で5を4にし、続いて「2倍」で4を8にします。これより少ない操作回数で8へ到達する方法は存在しないため、正解は2となります。
考え方:逆算アプローチ
この問題を効率的に解く鍵は、n から m へ向かって逆算することです。前方の操作「2倍」「−1」に対して、逆方向では次のように対応させられます。
- n が偶数の場合 → 2で割る(直前のステップで2倍されたと考えられるため)
- n が奇数の場合 → 1を足す(偶数にしてから2で割れるようにする)
- n が m 以下になったら → 残りの差(m − n)のぶんだけデクリメントを行う
この手法により、全パターンを探索する必要がなくなり、非常に高速に答えを導き出せます。while ループの各ステップで n はおおむね半分以下に減っていくため、計算量は O(log n) 程度に収まります。
コード例
上記のロジックを実装したコードがこちらです。
const m = 5;
const n = 8;
const findOperations = (m, n) => {
let res = 0;
while(n > m){
if(n % 2 === 0){
n /= 2;
}else{
n += 1;
};
res += 1;
};
return res + m - n;
};
console.log(findOperations(m, n));
コードのポイントは次のとおりです。
- n が m より大きい間、偶数なら2で割り、奇数なら1を足して操作回数をカウントします。
- ループを抜けた時点で n ≤ m になっているため、「res + m - n」で残りに必要なデクリメント回数を加算して返します。
出力
コンソールには次のように表示されます。
2
このように、逆算の発想を使えば一見複雑に思える最小操作回数の問題も、シンプルで効率的なコードで解決できます。
-
JavaScriptで数値が三角数かどうかを判定する方法
三角数(Triangular Number)とは? 三角数とは、点を正三角形の形に敷き詰めたときに現れる数のことです。n番目の三角数は「1からnまでの自然数の合計」として表され、次の公式で求められます。 Tn = n(n+1) / 2 具体的な三角数は 1, 3, 6, 10, 15, 21, 28 … と続きます。例えば 10 は、各辺に4個の点を配置した正三角形を構成できるため、三角数です。 問題 数値を引数として受け取り、その数値が三角数であれば true を、そうでなければ false を返すJavaScript関数を実装します。 判定の考え方 n(n+1)/2 = num となる正
-
C++でNからMに到達するまでの最小ステップ数を求める方法
2つの整数NとMが与えられたとき、以下の2種類の操作のみを使ってNからMに到達するために必要な最小ステップ数を求める問題について解説します。数xを2倍にする(xは2*xになる)数xから1を引く(xはx−1になる)例えば、N = 4、M = 6の場合、答えは2になります。まずNに対して「1を引く」操作を行うと3になり、続けて「2倍する」操作を行うと2 * 3 = 6となり、Mに到達できます。したがって、必要な最小ステップ数は2です。解法のアプローチ:問題を逆転させるこの問題を効率的に解く鍵となるのは、問題を逆向きに考えることです。NからMへ向かう代わりに、MからNへ向かうと考え直すと、操作は次の