ハッシュとヒープで出てくる回数の多い値を k 個選ぶ

ヒープ問題 53

整数の​並びから、​出てくる​回数の​多い​値を​ k 個、​決めた順で​返します。​辞書で​回数を​数え、​「いちばん弱い​候補」が​根に​来る​ヒープに​ k 個だけ​持つ練習です。

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

問題

整数の並び nums と、整数 k を受け取ります。nums の中で出てくる回数の多い値を k 個選び、並びにして返す関数を書いてください。

  • 返す順は、出てくる回数の多い順です。回数が同じ値どうしは、値の小さい順に並べます
  • 回数が同じ値が k 個目をまたぐときも、この順で前から k 個を選びます。例 2 を見てください
  • nums の長さは 1 以上 100000 以下、値はどれも -10000 以上 10000 以下です
  • k は 1 以上、nums にある違う値の数以下です
  • 違う値の数を u として、全部を並べ替える O(u log u) より速い、O(n log k) をめざしてください

入力と出力の例

例 1

4 は 3 回、2 は 2 回、1 と 3 は 1 回ずつ出てきます。多い方から 2 つは 4 と 2 です。

入力

nums = [4, 1, 4, 2, 2, 4, 3]
k = 2

出力

[4, 2]

例 2

5 と 7 は 2 回ずつで同じなので、値の小さい 5 が先です。9 は 1 回です。

入力

nums = [7, 5, 9, 7, 5]
k = 1

出力

[5]

例 3

値が 1 つだけです。

入力

nums = [-3]
k = 1

出力

[-3]

面接での聞かれ方

面接では、短く次のように渡されることが多いです。

  • 「配列の中で、出現回数が多い上位 k 個の要素を返してください」
  • 最初に並べ替えの書き方を出すと、「O(n log n) より速くできますか?」と寄せられます
  • 書き終えたあとに「回数が同じときはどう並べますか?」「回数の上限が n なのを使うと、もっと速くなりませんか?」と広げて聞かれます

返す順が決まっていない問題として出されることも多いので、順と同じ回数の扱いを最初に確かめて口に出します。

アルゴリズムのチートシートの「スタックとキュー」に、​この​型の​要点を​表と​コードで​まとめています。

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


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

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