Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions 703. Kth Largest Element in a Stream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# [703. Kth Largest Element in a Stream](https://leetcode.com/problems/kth-largest-element-in-a-stream/description/)

## Step1
### 問題意図の考察 (Heap, PriorityQueue)
- 与えられた整数kに対して、k番目に高いスコアを返すclassを実装する。全てのスコアをソートしたリストにおけるk番目に大きいスコアを求める。
- リアルタイムという点から、動的に更新されるデータの中で、常にk番目に高い値を効率的に取得する必要がある。
- 幾つの要素が来るかはわからないので、効率性が求められる。
- メモリの効率性を考えて、全部を保存するのではなく、その場で答えを出す。

### 解法を考える
- kthLargestのコンストラクタで、numsを読み込む。
- add(int val)では、新しいスコアvalをヒープに追加。
- カテゴリから推測するのは良くないが、heapで必要なメモリの確保か。ここにいきなりたどり着けるかな。
- 解法が浮かばなかったので、回答を見る。

```cpp
#include <queue>
#include <vector>

class KthLargest {
public:
KthLargest(int k, std::vector<int>& nums) : k_(k) {
for (int num : nums) {
add(num);
}
}

int add(int val) {
if (min_heap_.size() < k_) {
min_heap_.push(val);
}
else if (val > min_heap_.top()) {
min_heap_.pop();
min_heap_.push(val);
}
return min_heap_.top();
}

private:
int k_;
std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap_;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

データ構造を表す名前を変数名に入れても、あまり情報は増えないように思います。中にどのような値が含まれているかを変数名に付けたほうが読みやすくなると思います。 k_largest_values_ はいかがでしょうか?

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nodchip
ご返信随分と遅くなり大変申し訳ございません、

ご指摘頂いた通りですね。中身が何かをしっかりと意識した変数名をつけるようにします。

};

/**
* Your KthLargest object will be instantiated and called as such:
* KthLargest* obj = new KthLargest(k, nums);
* int param_1 = obj->add(val);
*/

```

## Step2
- いくつかのrepoを確認してみたが、良し悪しの判断ができなかった。いくつかの選択肢を書いて、判断したい。
- 「k番目に大きいスコアを教えて」-> 最大のk個だけ残しておけば、その中の最小値がk番目に大きい値になる。
- priority_queue:優先度付きのキュー
-> *std::queue: FIFO, に対し、std::priority_queue: 常に一番大きな値が前に出る。https://en.cppreference.com/w/cpp/container/priority_queue.html
*話が逸れるが、物流の在庫管理の考え方:先入先出(FIFO)やプリンタのキュー管理など、実社会にあるのも面白い。
*最大/最小を即座に取り出せる。O(log n)でpush/pop. top()はO(1).
- 時間がかかりすぎたので、他の解法の実装は別途。

```cpp
// 最大ヒープ(デフォルト)
std::priority_queue<int> max_heap;

// 最小ヒープ(今回)
std::priority_queue<int, std::vector<int>, std::greater<int>> min_heap;

// 操作
min_heap.push(x); // 値を追加
min_heap.top(); // 最小値を取得
min_heap.pop(); // 最小値を削除
min_heap.size();

```
### データ構造とアルゴリズム
- このstep2の際に、AL-Strategiesの観点も今後の学習の際に考えた方が、良い方針が立ちそう。
* Online Algorithm? 一件ずつ入力される前提 で動くアルゴリズム
* Heap Strategies 今回の実装
* Top-K Elements 配列の中で上位k件を常に求める。
* Streaming Process データが大量で、全部を保持できない。
- 目的:stream が次々とくる。オンライン。
- データサイズ:入力が無限に続く可能性有。全部保持したくない。
- * k は大きい?小さい?:ここで躓いた。どのくらいの高さになるかはlognから割り出せるが、それが大きい?小さい?の判断が良くわからない。
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

今回の問題は大学の入学試験という設定のようなので、どんなに大きくてもkは10万として、log_2(100000)≒17くらいなので小さいと考えてよさそうです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@maeken4
こちらご返信随分と遅くなり大変申し訳ございません。

コメントありがとうございます。
推定(概算)から考えるんですね。未経験なので、あまりここら辺の感覚がわからずでして。。。
もう少し当たり前の所を気を配っていきたいと思います。

* lognの計算量の実測データ(ベンチマーク)・CPUクロックから判断できるみたい。別途深掘りする。
- 更新:add(val)が何度も呼ばれる。

## Step3
45min