Skip to content

Commit df7a782

Browse files
authored
Merge pull request #23 from colorbox/703
703. Kth Largest Element in a Stream
2 parents 4d6aa32 + 5f7bd46 commit df7a782

File tree

10 files changed

+565
-0
lines changed

10 files changed

+565
-0
lines changed

703/step1_1.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Time(20:43)
3+
4+
KthLargest
5+
Space: O(N)
6+
Time: O(NlogN)
7+
8+
Add
9+
Space: O(1)
10+
Time: O(N)
11+
12+
毎回ソートをすると間違いなく時間が足りなくなるのでそうしないように実装する必要がある。
13+
ソート済みの配列の適切な位置に挿入することでaddを実装できると思ったのでそのように実装。
14+
15+
*/
16+
class KthLargest {
17+
vector<int> sorted;
18+
int target;
19+
public:
20+
KthLargest(int k, vector<int>& nums) {
21+
target = k;
22+
for (int num: nums) {
23+
sorted.push_back(num);
24+
}
25+
sort(sorted.begin(), sorted.end());
26+
}
27+
28+
int add(int val) {
29+
auto it = lower_bound(sorted.begin(), sorted.end(), val);
30+
sorted.insert(it, val);
31+
return sorted[sorted.size() - target];
32+
}
33+
};

703/step1_2.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
step1はaddメソッドのinsertによって時間計算量が最適ではなかったのでHeapを使うように再実装。
3+
メソッドを分けずにベタ書き。
4+
*/
5+
class KthLargest {
6+
private:
7+
std::vector<int> heap;
8+
int size;
9+
public:
10+
KthLargest(int k, vector<int>& nums): heap(nums), size(k) {
11+
// ソートしておけばmin heapとして問題ない状態になるはず
12+
sort(heap.begin(), heap.end());
13+
// heapの切り詰め、sizeで切り詰める
14+
while (heap.size() > k) {
15+
heap.erase(heap.begin());
16+
}
17+
}
18+
19+
int add(int val) {
20+
if (heap.empty()) {
21+
heap.push_back(val);
22+
return val;
23+
}
24+
// 末尾に加える
25+
heap.push_back(val);
26+
// heapfy
27+
// 末尾のインデックスとその親を見て、交換、その繰り返し
28+
int child_index = heap.size() - 1;
29+
int parent_index = (child_index - 1) / 2;
30+
while (heap[child_index] < heap[parent_index]) {
31+
swap(heap[child_index], heap[parent_index]);
32+
child_index = parent_index;
33+
parent_index = (child_index - 1) / 2;
34+
}
35+
// サイズ超過してなかったら最小要素を返して終わり
36+
if (heap.size() <= size) {
37+
return heap.front();
38+
}
39+
// サイズ超過してたら最小要素を削除して再構成
40+
swap(heap.front(), heap.back());
41+
heap.pop_back();
42+
// root要素を適切な位置に配置する
43+
parent_index = 0;
44+
int left_child_index = parent_index * 2 + 1;
45+
int right_child_index = parent_index * 2 + 2;
46+
while (left_child_index < heap.size() && heap[parent_index] > heap[left_child_index] || right_child_index < heap.size() && heap[parent_index] > heap[right_child_index]) {
47+
int swap_target_index = left_child_index;
48+
if (right_child_index < heap.size() && heap[swap_target_index] > heap[right_child_index]) {
49+
swap_target_index = right_child_index;
50+
}
51+
swap(heap[parent_index], heap[swap_target_index]);
52+
parent_index = swap_target_index;
53+
left_child_index = parent_index * 2 + 1;
54+
right_child_index = parent_index * 2 + 2;
55+
}
56+
return heap.front();
57+
}
58+
};
59+

703/step2_1.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
class KthLargest {
2+
private:
3+
std::vector<int> heap;
4+
int size;
5+
public:
6+
KthLargest(int k, vector<int>& nums): heap(nums), size(k) {
7+
// ソートしておけばmin heapとして問題ない状態になるはず
8+
sort(heap.begin(), heap.end());
9+
// heapの切り詰め、sizeで切り詰める
10+
while (heap.size() > k) {
11+
heap.erase(heap.begin());
12+
}
13+
}
14+
15+
int add(int val) {
16+
heap.push_back(val);
17+
int child_index = heap.size() - 1;
18+
while (true) {
19+
int parent_index = (child_index - 1) / 2;
20+
if (heap[child_index] >= heap[parent_index]) {
21+
break;
22+
}
23+
swap(heap[child_index], heap[parent_index]);
24+
child_index = parent_index;
25+
}
26+
if (heap.size() <= size) {
27+
return heap.front();
28+
}
29+
swap(heap.front(), heap.back());
30+
heap.pop_back();
31+
int parent_index = 0;
32+
while (true) {
33+
int left_child_index = parent_index * 2 + 1;
34+
if (left_child_index >= heap.size()) {
35+
break;
36+
}
37+
int swap_target_index = left_child_index;
38+
int right_child_index = left_child_index + 1;
39+
if (right_child_index < heap.size() && heap[left_child_index] > heap[right_child_index]) {
40+
swap_target_index = right_child_index;
41+
}
42+
if (heap[swap_target_index] >= heap[parent_index]) {
43+
break;
44+
}
45+
swap(heap[parent_index], heap[swap_target_index]);
46+
parent_index = swap_target_index;
47+
}
48+
return heap.front();
49+
}
50+
};
51+

703/step2_2.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
サイズを制限したpriority_queueでも実装できるのでそれを実装。
3+
*/
4+
class KthLargest {
5+
private:
6+
priority_queue<int, vector<int>, greater<int>> q;
7+
int size;
8+
public:
9+
KthLargest(int k, vector<int>& nums): size(k) {
10+
for (int num: nums) {
11+
q.push(num);
12+
}
13+
}
14+
15+
int add(int val) {
16+
q.push(val);
17+
while (q.size() > size) {
18+
q.pop();
19+
}
20+
return q.top();
21+
}
22+
};
23+

703/step2_3.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
heapを自前で実装
3+
*/
4+
class KthLargest {
5+
public:
6+
KthLargest(int k, vector<int>& nums): capacity(k) {
7+
for (int num: nums) {
8+
push(num);
9+
}
10+
11+
while (container.size() > capacity) {
12+
pop();
13+
}
14+
}
15+
16+
int add(int val) {
17+
push(val);
18+
return top();
19+
}
20+
21+
private:
22+
vector<int> container;
23+
int capacity;
24+
25+
int top() {
26+
return container.front();
27+
}
28+
29+
void pop() {
30+
swap(container.front(), container.back());
31+
container.pop_back();
32+
sift_down_from_root();
33+
}
34+
35+
void push(int val) {
36+
container.push_back(val);
37+
sift_up_from_leaf(container.size() - 1);
38+
while (size() > capacity) {
39+
pop();
40+
}
41+
}
42+
43+
int size() {
44+
return container.size();
45+
}
46+
47+
int parent_index(int child_index) {
48+
return (child_index - 1) / 2;
49+
}
50+
51+
int left_child_index(int parent_index) {
52+
return parent_index * 2 + 1;
53+
}
54+
55+
int right_child_index(int parent_index) {
56+
return left_child_index(parent_index) + 1;
57+
}
58+
59+
void sift_down_from_root() {
60+
int parent = 0;
61+
while (true) {
62+
int left = left_child_index(parent);
63+
if (left >= size()) {
64+
return;
65+
}
66+
int min_child_index = left;
67+
int right = right_child_index(parent);
68+
if (right < size() && container[min_child_index] > container[right]) {
69+
min_child_index = right;
70+
}
71+
if (container[min_child_index] >= container[parent]) {
72+
return;
73+
}
74+
swap(container[parent], container[min_child_index]);
75+
parent = min_child_index;
76+
}
77+
}
78+
79+
void sift_up_from_leaf(int index) {
80+
int child_index = index;
81+
int parent_index_ = parent_index(child_index);
82+
while (parent_index_ >= 0) {
83+
if (container[parent_index_] <= container[child_index]) {
84+
return;
85+
}
86+
swap(container[parent_index_], container[child_index]);
87+
child_index = parent_index_;
88+
parent_index_ = parent_index(parent_index_);
89+
}
90+
}
91+
};

703/step2_4.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
https://github.com/Ryotaro25/leetcode_first60/pull/9/files#r1619710596
3+
https://discord.com/channels/1084280443945353267/1183683738635346001/1185972070165782688
4+
を参考にmultisetを使用した解法を実装
5+
*/
6+
class KthLargest {
7+
private:
8+
multiset<int> s;
9+
int capacity;
10+
public:
11+
KthLargest(int k, vector<int>& nums): capacity(k) {
12+
for (int num: nums) {
13+
s.insert(num);
14+
}
15+
16+
while (s.size() > capacity) {
17+
s.erase(s.begin());
18+
}
19+
}
20+
21+
int add(int val) {
22+
if (s.size() == capacity && val < *s.begin()) {
23+
return *s.begin();
24+
}
25+
s.insert(val);
26+
if (s.size() > capacity) {
27+
s.erase(s.begin());
28+
}
29+
return *s.begin();
30+
}
31+
};

703/step3.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
class KthLargest {
2+
private:
3+
priority_queue<int, vector<int>, greater<int>>queue;
4+
int capacity;
5+
public:
6+
KthLargest(int k, vector<int>& nums): capacity(k) {
7+
for (int num: nums) {
8+
queue.push(num);
9+
}
10+
}
11+
12+
int add(int val) {
13+
queue.push(val);
14+
while (queue.size() > capacity) {
15+
queue.pop();
16+
}
17+
return queue.top();
18+
}
19+
};

0 commit comments

Comments
 (0)