文字列メソッド・配列なしでJavaScriptの整数の桁を並べ替える方法
問題の概要
数値を引数として受け取り、その桁を並べ替えて作れる「最小の数」を返すJavaScript関数を作成します。
たとえば、入力が次の数値だった場合:
const num = 614532;
出力は次のようになります:
const output = 123456;
制約条件
この問題には重要な条件があります。Stringオブジェクトのメソッドは一切使えず、データの格納に配列も使用できないという点です。つまり、純粋な数値演算だけで各桁を並べ替える必要があります。
実装コード
const num = 614532;
const sortDigits = num => {
const getDigit = e => Math.floor(num / 10 ** e) % 10;
const l = Math.ceil(Math.log10(num)) − 1;
let e = l;
while (e−−) {
const left = getDigit(e + 1);
const right = getDigit(e);
if (left <= right){
continue;
};
num += (right − left) * 9 * 10 ** e;
e = l;
};
return num;
}
console.log(sortDigits(num));出力結果
コンソールには次のように表示されます:
123456
コードの解説
このアルゴリズムのポイントは以下の通りです。
1. 桁の取り出し(getDigit関数)
Math.floorと剰余演算(%)を組み合わせることで、指定した位の桁を数値のまま取り出しています。Math.floor(num / 10 ** e) % 10により、10のe乗の位の数字だけを抽出でき、文字列への変換は一切不要です。
2. 桁数の算出
Math.log10で常用対数を求め、Math.ceilして1を引くことで、最上位の桁の指数を導き出しています。これによりループの開始位置が決まります。
3. 隣接桁の交換
より上位の桁(left)が下位の桁(right)より大きい場合、num += (right − left) * 9 * 10 ** eという式で2つの桁を入れ替えます。この式は、2桁の差分を一括して補正することでスワップと同じ効果を実現する巧妙なテクニックです。考え方としてはバブルソートと同じです。
4. 繰り返し処理
交換が発生した場合は、最上位から再度チェックを行うためeを初期化してやり直します。すべての桁が昇順に並ぶまで処理を繰り返すことで、結果的に最小の数が完成します。
なお、この手法の計算量はバブルソートと同様に最悪ケースでO(n²)となりますが、桁数は高々10桁程度であるため、実用上は十分高速に動作します。
-
JavaScriptで2つの配列をマージして重複を削除する方法
課題 JavaScriptで、2つの数値の配列 arr1 と arr2 を引数として受け取る関数を作成することを考えます。 この関数は、両方の配列の要素を1つの新しい配列にマージします。マージの前後いずれかの時点で重複する要素が存在した場合には、余分なコピーを削除し、各要素が必ず1回だけ現れるようにしなければなりません。 要素の並び順は厳密には問われませんが、各要素の出現回数(必ず1回であること)が重要なポイントになります。 入力例 const arr1 = [6, 5, 2, 1, 8]; const arr2 = [3, 4, 6, 8, 9]; この場合、期待される出力は次のとおりです。
-
JavaScriptで文字列内のアルファベットだけを反転する方法
問題の概要JavaScriptで、アルファベットといくつかの特殊文字(記号)が混在する文字列 str を受け取る関数を作成することを求められています。この関数は、入力文字列をもとに新しい文字列を返します。その際のルールは次のとおりです。アルファベット以外の文字(記号・数字など)は、元の位置にそのまま留まります。アルファベットの文字だけが、互いに反転した位置へ移動します。入力例と出力例たとえば、関数への入力が以下だった場合を考えてみましょう。入力const str = k_lmn_opq;出力const output = q_pon_mlk;「_」という記号は位置が変わっておらず、アルファベット