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

JavaScriptで文字列内の子音だけを反転する方法

問題の概要

小文字の英字アルファベットのみで構成された文字列を引数として受け取るJavaScript関数を作成します。

この関数が返すべきは、子音の並び順だけを逆順に入れ替えた新しい文字列です。母音(a・e・i・o・u)は元の位置にそのまま残ります。

入力例

const str = 'somestring';

出力例

子音「s, m, s, t, r, n, g」を逆順にすると「g, n, r, t, s, m, s」になり、これを母音を動かさずに元の位置へ当てはめると、次のような結果になります。

const output = 'gonertsims';

アプローチ:両端から走査するツーポインタ法

この問題を効率的に解くには、文字列を配列に変換したうえで、先頭と末尾から同時に走査するツーポインタ(two-pointer)テクニックが有効です。手順は以下のとおりです。

  1. split('') で文字列を配列に変換します。
  2. 先頭ポインタ i を進め、子音が見つかるまで移動します。
  3. 末尾ポインタ j を戻しながら、子音が見つかるまで移動します。
  4. 両方の子音が見つかったら互いに交換し、ポインタを内側へ1つずつ進めます。
  5. i < j が成立している間、この処理を繰り返します。

この方法なら時間計算量は O(n) で済み、余分なメモリの消費も最小限に抑えられます。

コード例

const str = 'somestring';

const reverseConsonants = (str = '') => {
  const arr = str.split('');
  let i = 0, j = arr.length - 1;
  // 注意:「m」を含め忘れると結果が変わるので、子音リストは正確に定義する
  const consonants = 'bcdfghjklmnpqrstvwxyz';
  while (i < j) {
    // 先頭側の子音を探す
    while (i < j && consonants.indexOf(arr[i]) < 0) {
      i++;
    }
    // 末尾側の子音を探す
    while (i < j && consonants.indexOf(arr[j]) < 0) {
      j--;
    }
    // 子音同士を交換
    [arr[i], arr[j]] = [arr[j], arr[i]];
    i++;
    j--;
  }
  return arr.join('');
};

console.log(reverseConsonants(str));

ポイントは次の2つです。

  • 子音リストの定義ミスに注意:「bcdfghjklnpqrstvwxyz」のように「m」が抜けていると、m が母音扱いされて位置が動かなくなり、誤った結果になります。正しくは「bcdfghjklmnpqrstvwxyz」です。
  • 配列の分割代入でスワップ:一時変数を使わず [arr[i], arr[j]] = [arr[j], arr[i]]; と書くことで、コードがより簡潔になります。また、結果の組み立てには join('') を使うとループ処理が不要になります。

出力

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

gonertsims

まとめ

文字列の中で特定の種類の文字だけを入れ替えたい場合、「対象以外の文字の位置は固定する」という条件を、両端からの走査で自然に実現できます。母音をスキップして子音だけを交換するこのパターンは、同様の文字列操作問題にも応用できる汎用的なテクニックです。

  1. JavaScriptで文字列内のアルファベットだけを反転する方法

    問題の概要JavaScriptで、アルファベットといくつかの特殊文字(記号)が混在する文字列 str を受け取る関数を作成することを求められています。この関数は、入力文字列をもとに新しい文字列を返します。その際のルールは次のとおりです。アルファベット以外の文字(記号・数字など)は、元の位置にそのまま留まります。アルファベットの文字だけが、互いに反転した位置へ移動します。入力例と出力例たとえば、関数への入力が以下だった場合を考えてみましょう。入力const str = k_lmn_opq;出力const output = q_pon_mlk;「_」という記号は位置が変わっておらず、アルファベット

  2. JavaScriptで文字列内の文字を英字・数字・特殊文字に再グループ化する方法

    問題文字列 str を第一引数(唯一の引数)として受け取る JavaScript 関数を作成する必要があります。この文字列には、次の3種類の文字が含まれる可能性があります。英字:(A-Z)、(a-z)数字:0〜9特殊文字:上記以外のすべての文字関数は文字列を先頭から順に走査し、ちょうど3つの要素からなる配列を構築します。1番目の要素には文字列に含まれるすべての英字、2番目には数字、3番目には特殊文字を格納し、それぞれ元の文字列内での出現順(相対的な順序)を維持します。最後にこの配列を返します。例えば、関数への入力が次の場合を考えてみましょう。入力const str = thi!1s is S@