ゆめさくエンジニア研究所
再帰問題 11

入れ子の​並びを​平らにする

整数と​並びが​入れ子に​なった​並びから、​中の​整数を​左から​順に​ 1 段の​並びに​して​返します。​並びの​中の​並びを​同じ​関数に​任せる、​再帰の​練習です。

問題

並び items を受け取ります。items の中身は整数か、また別の並びです。その並びの中にも、整数と並びが入っています。中にある整数を全部、左から順に取り出して、1 段だけの並びにして返す関数を書いてください。

  • 入れ子の深さに決まりはありません。ただし、一番深いところでも 100 段までです
  • 空の並びが中に入っていることもあります。空の並びからは何も取り出しません
  • 中にある整数の数は、全部で 0 以上 10000 以下です

入力と出力の例

例 1

入力

items = [1, [2, 3], 4]

出力

[1, 2, 3, 4]

例 2

深さが違っても、左から順に取り出します。

入力

items = [[5, [6, [7]]], 8, [9]]

出力

[5, 6, 7, 8, 9]

例 3

空の並びからは何も取り出しません。

入力

items = [[], [-1, []], 0]

出力

[-1, 0]

面接での聞かれ方

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

  • 「入れ子になった配列を平らにしてください」
  • 書き終えたあとに「入れ子がとても深いとどうなりますか?」と聞かれることがあります
  • 「再帰を使わずに書けますか?」と、別の書き方を求められることもあります

深さに決まりがあるのか、空の並びが入るのか、整数以外が入るのかを、書く前に確かめておきます。

まず考える手順

段 1

まず、深さが 1 段だけの場合を考えます。items を前から見て、整数ならそのまま答えに足し、並びなら中の整数を順に足します。繰り返しを 2 重にすれば書けます。

段 2

深さが 2 段、3 段と増えると、そのたびに繰り返しを 1 重ずつ足すことになります。深さに決まりが無いので、この書き方では書き切れません。ここで、並びの中の並びも「入れ子の並びを平らにする」という同じ問題だ、と気づくことが大切です。

段 3

そこで、並びに出会ったら、いま書いている関数そのものに任せます。任された関数は、その並びを平らにした結果を返すので、それを答えに足します。整数に出会ったときは、もう分ける必要が無いので、そのまま足します。これが止まる条件です。

段 4

結果を足す手間も気にします。呼び出すたびに新しい並びを作ってつなげると、深い所の整数は何度も写されます。そこで、答えの並びを 1 つだけ用意し、補助の関数がその並びに直接書き足すようにします。

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

解答

Python

Python

def flatten(items):
    out = []

    def walk(xs):
        for x in xs:
            if type(x) is list:
                walk(x)
            else:
                out.append(x)

    walk(items)
    return out

JavaScript

JavaScript

function flatten(items) {
  const out = [];
  function walk(xs) {
    for (const x of xs) {
      if (Array.isArray(x)) {
        walk(x);
      } else {
        out.push(x);
      }
    }
  }
  walk(items);
  return out;
}

補助の関数 walk は、並びを 1 つ受け取り、整数なら out に足し、並びなら自分をもう一度呼びます。並びの中が空なら繰り返しが 1 回も回らず、そのまま戻ります。

計算量

  • 時間は O(n) です。ここでの n は、整数と並びを合わせた中身の数です。どの中身も 1 回ずつ見ます
  • 使う記憶は、答えの並びの O(n) と、呼び出しが重なる深さ d の分の O(d) です
  • 呼び出しは、深さの分だけ重なります。Python は既定で約 1000 段を超えると止まるので、この問題の 100 段までなら心配ありません。深さに決まりが無いなら、自分でスタックを持つ書き方に変えます

よくある間違い

  • 止まる条件を書き忘れる。整数のときに自分を呼ばずに足す、という分かれ道が止まる条件です。これが無いと、整数を並びとして扱おうとして止まります
  • 呼び出しの結果を受け取り忘れる。補助の関数を使わずに書くなら、flatten(x) が返した並びを答えにつなげる必要があります。呼ぶだけで捨てると、深い所の整数が消えます
  • 並びかどうかを長さで見分ける。 Python の len や JavaScript の length で見分けようとすると、整数で例外が出たり、空の並びを取り違えたりします。Python は isinstance(x, list)、JavaScript は Array.isArray(x) で見分けます

面接での話し方の例

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

「並びの中の並びも、平らにするという同じ問題なので、再帰で書きます。整数ならそのまま答えに足し、これが止まる条件です。並びなら同じ関数に任せます。答えの並びは 1 つだけにして、写す手間を増やさないようにします。」

書き終えたら、深さについても一言添えます。

「呼び出しは入れ子の深さの分だけ重なります。今回は 100 段までなので大丈夫ですが、もっと深くなるなら、自分でスタックを持って繰り返しで書く形に変えます。」

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

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