ソートとツーポインタで和が目標になる 4 つの組を全部集める

整数の​並びから、​足すと​目標に​なる​ 4 つの​数の​組を、​重ならないように​全部返します。​並べ替えてから​外側の​数を​順に​決め、​最後の​ 2 つを​両端の​指で​探す形に​組み立てる​練習です。

海外で定番の問題リスト 4 本には入っていません

問題

整数の並び nums と、整数 target を受け取ります。nums から位置の違う 4 つの数を選び、足すと target になる組を全部返す関数を書いてください。返すのは位置ではなく、数の値の組です。

  • 値の組み合わせが同じものは 1 回だけ返します。たとえば [1, 1, 2] から選んだ 2 つの 1 は、どちらの 1 を使っても同じ組です
  • 組の中は小さい順に並べます。組どうしは辞書の順 (先頭の数から比べ、小さいほうが先。同じなら次の数で比べる) に並べます
  • そういう組が 1 つも無いとき、nums の長さが 4 より短いときは、空の並び [] を返します
  • nums の長さは 1 以上 200 以下、値はどれも絶対値が 10 億以下、target は絶対値が 10 億以下です。4 つの和は 40 億近くになることがあります

入力と出力の例

例 1

入力

nums = [3, -1, 0, 2, -2, 1]
target = 2

出力

[[-2, -1, 2, 3],
 [-2, 0, 1, 3],
 [-1, 0, 1, 2]]

例 2

同じ値が 2 つずつあります。-1 と 0 と 0 と 1 の組は、どの -1 とどの 1 を使っても 1 回だけ数えます。

入力

nums = [-1, 0, 1, -1, 0, 1]
target = 0

出力

[[-1, -1, 1, 1],
 [-1, 0, 0, 1]]

例 3

5 つ全部が同じ値でも、組は 1 つだけです。

入力

nums = [2, 2, 2, 2, 2]
target = 8

出力

[[2, 2, 2, 2]]

面接での聞かれ方

面接では、2 つの和や 3 つの和の問題を解いたあとに、数を増やした続きとして出されることが多いです。

  • 「では 4 つならどうしますか? 3 つのときの書き方を使えますか?」と、前の解き方を広げられるかを聞かれます
  • 「同じ組を 2 回出さないようにするには、どこで飛ばしますか?」と、重なりの消し方を細かく聞かれます
  • 書き終えたあとに「5 つ、6 つと増えたらどう書きますか?」「4 つの和は、どの型の整数に入りますか?」と続きます

外側で 1 つずつ数を決めて、残りを「1 つ少ない和の問題」へ渡す形にしておくと、4 つでも 5 つでも同じ関数で書けます。

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

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


# 「実行」を押すと、この行の結果が出ます
print(four_sum([3, -1, 0, 2, -2, 1], 2))

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