ゆめさくエンジニア研究所
文字列問題 01

単語の​並びを逆にする

空白で​区切られた​単語の​順を​逆に​して、​空白 1 つで​つなぎ直す。​文字列を​前から​読んで、​単語の​始まりと​終わりを​自分で​見つける​練習です。

問題

文字列 s を受け取ります。s は、空白で区切られたいくつかの単語でできています。単語の順を逆にして、単語と単語の間を空白 1 つでつないだ文字列を返す関数を書いてください。

  • 単語は、空白を含まない 1 文字以上のひとまとまりです
  • 先頭と末尾の空白は捨てます。単語の間に空白が 2 つ以上続いていても、返す文字列では 1 つにします
  • 単語が 1 つも無いときは、空の文字列を返します
  • s の長さは 0 以上 10000 以下で、英字、数字、半角の空白だけでできています

入力と出力の例

例 1

入力

s = "cats like warm milk"

出力

"milk warm like cats"

例 2

先頭と末尾の空白は消え、続いた空白は 1 つになります。

入力

s = "  open   the door "

出力

"door the open"

例 3

単語が 1 つだけなら、そのまま返します。

入力

s = "hello"

出力

"hello"

面接での聞かれ方

面接では、短い一言で渡されることが多いです。

  • 「文の単語の順番を逆にしてください」
  • 書き終えたあとに「split を使わずに書けますか?」と続けて聞かれます
  • 「空白が続いていたら?」「空の文字列なら?」と、端の場合を聞かれることもあります

単語の中の文字まで逆にするのか、単語の順だけを逆にするのかを、最初に確かめておくと安心です。空白の扱いも、書き始める前に口で決めておきます。

まず考える手順

段 1

まずは素直に、言語に用意された道具を使います。Python なら s.split() で単語の並びが取れ、reversed で逆にして " ".join でつなげば終わりです。引数なしの split() は、続いた空白も先頭と末尾の空白もまとめて捨ててくれます。

段 2

面接では「split を使わずに」と言われることがよくあります。そのときは、文字列を前から 1 文字ずつ読み、単語の始まりと終わりを自分で見つけます。空白なら読み飛ばし、空白でない文字に当たったら、そこが単語の始まりです。

段 3

始まりの位置 i から、空白に当たるか文字列の終わりに来るまで、もう 1 つの位置 j を進めます。i から j の手前までが 1 つの単語なので、それを並びに足し、i を j に進めて続けます。最後に並びを逆にして空白 1 つでつなげば、段 1 と同じ答えになります。

ここから​解答です。​先に​自分で​書いてから​読むと、​考え方が​残ります。

解答

Python

Python

def reverse_words(s):
    words = []
    i = 0
    n = len(s)
    while i < n:
        if s[i] == " ":
            i += 1
            continue
        j = i
        while j < n:
            if s[j] == " ":
                break
            j += 1
        words.append(s[i:j])
        i = j
    words.reverse()
    return " ".join(words)

JavaScript

JavaScript

function reverseWords(s) {
  const words = [];
  const n = s.length;
  let i = 0;
  while (i < n) {
    if (s[i] === " ") {
      i++;
      continue;
    }
    let j = i;
    while (j < n) {
      if (s[j] === " ") {
        break;
      }
      j++;
    }
    words.push(s.slice(i, j));
    i = j;
  }
  words.reverse();
  return words.join(" ");
}

段 2 と段 3 の、単語を自分で切り出す書き方です。段 1 の書き方なら、Python は " ".join(reversed(s.split())) の 1 行で同じ答えになります。

計算量

  • 時間は O(n) です。i と j はどちらも前にしか進まないので、文字は合わせて一定の回数しか読みません
  • 使う記憶は O(n) です。切り出した単語を並びに覚え、つないだ文字列も新しく作ります
  • 段 1 の split を使う書き方も、時間と記憶はどちらも O(n) です

よくある間違い

  • JavaScript で s.split(" ") を使う。 空白 1 つで区切ると、続いた空白や先頭の空白のところに空の文字列が入ります。例 2 で "door the open" のように、空白が多いまま返ってしまいます
  • 単語の中の文字まで逆にする。文字列をまるごと逆にすると "klim mraw ekil stac" になります。逆にするのは単語の順だけです
  • 内側の繰り返しで終わりを確かめ忘れる。 j < n を先に書かないと、最後の単語で文字列の外を読みにいきます

面接での話し方の例

書き始める前に、方針を短く口に出します。

「空白で単語に分けて、並びを逆にして、空白 1 つでつなぎます。split を使えば 1 行ですが、使わない書き方もできます。前から読んで、空白は飛ばし、空白でない文字から次の空白までを 1 つの単語として切り出します。時間も記憶も O(n) です。」

書き終えたら、例を 1 つ手でたどって見せます。

「例 2 の " open the door " でたどります。先頭の空白 2 つは飛ばし、open を切り出します。続く空白 3 つも飛ばすので、空の単語は入りません。最後に open、the、door の並びを逆にして、door the open を返します。」

解答を動かした版 Python 3.12.14Node.js 22.23.4確認日 2026年10月24日

コーディング面接問題の一覧へ戻る