Files
Ikko Eltociear Ashimine 954c45864b docs: add Japanese translate documents (#1812)
* docs: add Japanese documents (`ja/docs`)

* docs: add Japanese documents (`ja/codes`)

* docs: add Japanese documents

* Remove pythontutor blocks in ja/

* Add an empty at the end of each markdown file.

* Add the missing figures (use the English version temporarily).

* Add index.md for Japanese version.

* Add index.html for Japanese version.

* Add missing index.assets

* Fix backtracking_algorithm.md for Japanese version.

* Add avatar_eltociear.jpg. Fix image links on the Japanese landing page.

* Add the Japanese banner.

---------

Co-authored-by: krahets <krahets@163.com>
2025-10-17 05:04:43 +08:00

74 lines
3.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Top-k問題
!!! question
長さ$n$の順序付けられていない配列`nums`が与えられたとき、配列内の最大$k$個の要素を返してください。
この問題について、まず2つの直接的な解法を紹介し、次により効率的なヒープベースの方法を説明します。
## 方法1反復選択
下図に示すように、$k$回の反復を実行し、各回で$1$番目、$2$番目、$\dots$、$k$番目に大きい要素を抽出できます。時間計算量は$O(nk)$です。
この方法は$k \ll n$の場合にのみ適しています。$k$が$n$に近い場合、時間計算量は$O(n^2)$に近づき、非常に時間がかかります。
![最大k個の要素を反復的に見つける](top_k.assets/top_k_traversal.png)
!!! tip
$k = n$の場合、完全に順序付けられたシーケンスを得ることができ、これは「選択ソート」アルゴリズムと同等です。
## 方法2ソート
下図に示すように、まず配列`nums`をソートし、次に最後の$k$個の要素を返すことができます。時間計算量は$O(n \log n)$です。
明らかに、この方法はタスクを「やりすぎ」ています。最大$k$個の要素を見つけるだけでよく、他の要素をソートする必要はありません。
![ソートによる最大k個の要素の発見](top_k.assets/top_k_sorting.png)
## 方法3ヒープ
以下のプロセスに示すように、ヒープに基づいてTop-k問題をより効率的に解決できます。
1. 最小ヒープを初期化します。先頭要素が最小になります。
2. まず、配列の最初の$k$個の要素をヒープに挿入します。
3. $k + 1$番目の要素から開始し、現在の要素がヒープの先頭要素より大きい場合、ヒープの先頭要素を削除し、現在の要素をヒープに挿入します。
4. 走査を完了した後、ヒープには最大$k$個の要素が含まれています。
=== "<1>"
![ヒープに基づく最大k個の要素の発見](top_k.assets/top_k_heap_step1.png)
=== "<2>"
![top_k_heap_step2](top_k.assets/top_k_heap_step2.png)
=== "<3>"
![top_k_heap_step3](top_k.assets/top_k_heap_step3.png)
=== "<4>"
![top_k_heap_step4](top_k.assets/top_k_heap_step4.png)
=== "<5>"
![top_k_heap_step5](top_k.assets/top_k_heap_step5.png)
=== "<6>"
![top_k_heap_step6](top_k.assets/top_k_heap_step6.png)
=== "<7>"
![top_k_heap_step7](top_k.assets/top_k_heap_step7.png)
=== "<8>"
![top_k_heap_step8](top_k.assets/top_k_heap_step8.png)
=== "<9>"
![top_k_heap_step9](top_k.assets/top_k_heap_step9.png)
サンプルコードは以下の通りです:
```src
[file]{top_k}-[class]{}-[func]{top_k_heap}
```
合計$n$回のヒープ挿入と削除が実行され、最大ヒープサイズが$k$であるため、時間計算量は$O(n \log k)$です。この方法は非常に効率的で、$k$が小さい場合、時間計算量は$O(n)$に近づき、$k$が大きい場合でも、時間計算量は$O(n \log n)$を超えません。
さらに、この方法は動的データストリームのシナリオに適しています。データを継続的に追加することで、ヒープ内の要素を維持し、最大$k$個の要素の動的更新を実現できます。