バックトラックで並べ方を全部作る

違う​数ばかりの​並びから、​全部の​数を​ 1 回ずつ​使った​並べ方を​残らず作る。​1 つ​選んでは​先へ​進み、​戻る​ときに​選んだ印を​外す、​バックトラックの​基本の形です。

海外で定番の問題リスト 4 本のうち 3 本に入っています (NeetCode 150、Grind 75、LeetCode Top Interview 150)

問題

どれも違う値の整数の並び nums を受け取ります。nums の数を全部 1 回ずつ使って作れる並べ方を、全部返す関数を書いてください。

  • 返す順は次の決まりに従います。並べ方の 1 つ目の数は、nums で前にある数を先に選びます。1 つ目が同じ並べ方どうしは、2 つ目の数を、残りの数のうち nums で前にある方から選びます。3 つ目からも同じです
  • たとえば nums = [2, 1] なら、[2, 1] が先、[1, 2] が後です。値の大小ではなく、nums の中の位置で順が決まります
  • nums の長さは 1 以上 6 以下、値はどれも絶対値が 10 以下です

入力と出力の例

例 1

1 つ目に 4、7、1 の順で選び、それぞれ残りを前から選びます。

入力

nums = [4, 7, 1]

出力

[[4, 7, 1], [4, 1, 7],
 [7, 4, 1], [7, 1, 4],
 [1, 4, 7], [1, 7, 4]]

例 2

2 つなら、並べ方は 2 通りです。負の数も入ります。

入力

nums = [0, -2]

出力

[[0, -2], [-2, 0]]

例 3

1 つだけなら、並べ方は 1 通りです。

入力

nums = [5]

出力

[[5]]

面接での聞かれ方

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

  • 「重複の無い配列の、全部の順列を返してください」
  • 書き終えたあとに「答えはいくつになりますか」「計算量は?」と、答えの数そのものが大きいことに気づいているかを聞かれます
  • 「値に重複があったらどうしますか」と、続きの問題を聞かれることもあります

返す順を問わない面接も多いですが、試験の答えと比べる場ではずれると落ちます。順を決める必要があるかを先に確かめ、決めるなら「元の並びで前にある数から選ぶ」のように言葉で言える決まりにします。

アルゴリズムのチートシートの「再帰と木」に、​この​型の​要点を​表と​コードで​まとめています。

main.py
def permute(nums):
    # ここに書きます
    pass


# 「実行」を押すと、この行の結果が出ます
print(permute([4, 7, 1]))

できているか「例で確かめる」を押すと、問題の例を全部この関数に渡して、通ったかをここに出します