ヒープで k 番目に大きい値を求める

ヒープ問題 52

整数の​並びから、​大きい方から​数えて​ k 番目の​値を​返します。​全部を​並べ替えず、​大きい方の​ k 個だけを​小さい​順の​ヒープに​持ち続ける​練習です。

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

問題

整数の並び nums と、整数 k を受け取ります。nums を大きい順に並べたとき、前から k 番目に来る値を返す関数を書いてください。

  • 同じ値もそれぞれ 1 つと数えます。[9, 9, 7] で 2 番目に大きい値は 9 です
  • nums の長さは 1 以上 100000 以下、値はどれも -10000 以上 10000 以下です
  • k は 1 以上、nums の長さ以下です
  • 全部を並べ替える O(n log n) ではなく、ヒープを使って O(n log k) で求めてください

入力と出力の例

例 1

大きい順に並べると 9, 9, 7, 4, 2, 1 で、2 番目は 9 です。

入力

nums = [7, 2, 9, 4, 9, 1]
k = 2

出力

9

例 2

大きい順に 8, 6, 5, 3 で、3 番目は 5 です。

入力

nums = [5, 3, 8, 6]
k = 3

出力

5

例 3

値が 1 つだけです。

入力

nums = [-4]
k = 1

出力

-4

面接での聞かれ方

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

  • 「配列の中で k 番目に大きい要素を返してください。並べ替えずにできますか?」
  • ヒープの書き方を出すと、「なぜ大きい順ではなく小さい順のヒープなのですか?」と理由を聞かれます
  • 書き終えたあとに「値が流れてくる (全部が先にそろわない) としたら?」「平均 O(n) の書き方は知っていますか?」と広げて聞かれます

同じ値を別々に数えるか ([9, 9, 7] の 2 番目は 9 か 7 か) を最初に確かめておくと、間違いを 1 つ減らせます。

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

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


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

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