Skip to content

Commit 0f62b5f

Browse files
committed
New Problem Solution - "1825. Finding MK Average"
1 parent 55fc93d commit 0f62b5f

File tree

2 files changed

+276
-0
lines changed

2 files changed

+276
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ LeetCode
99

1010
| # | Title | Solution | Difficulty |
1111
|---| ----- | -------- | ---------- |
12+
|1825|[Finding MK Average](https://leetcode.com/problems/finding-mk-average/) | [C++](./algorithms/cpp/findingMkAverage/FindingMkAverage.cpp)|Hard|
1213
|1824|[Minimum Sideway Jumps](https://leetcode.com/problems/minimum-sideway-jumps/) | [C++](./algorithms/cpp/minimumSidewayJumps/MinimumSidewayJumps.cpp)|Medium|
1314
|1823|[Find the Winner of the Circular Game](https://leetcode.com/problems/find-the-winner-of-the-circular-game/) | [C++](./algorithms/cpp/findTheWinnerOfTheCircularGame/FindTheWinnerOfTheCircularGame.cpp)|Medium|
1415
|1822|[Sign of the Product of an Array](https://leetcode.com/problems/sign-of-the-product-of-an-array/) | [C++](./algorithms/cpp/signOfTheProductOfAnArray/SignOfTheProductOfAnArray.cpp)|Easy|
Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
// Source : https://leetcode.com/problems/finding-mk-average/
2+
// Author : Hao Chen
3+
// Date : 2021-04-20
4+
5+
/*****************************************************************************************************
6+
*
7+
* You are given two integers, m and k, and a stream of integers. You are tasked to implement a data
8+
* structure that calculates the MKAverage for the stream.
9+
*
10+
* The MKAverage can be calculated using these steps:
11+
*
12+
* If the number of the elements in the stream is less than m you should consider the
13+
* MKAverage to be -1. Otherwise, copy the last m elements of the stream to a separate container.
14+
* Remove the smallest k elements and the largest k elements from the container.
15+
* Calculate the average value for the rest of the elements rounded down to the nearest
16+
* integer.
17+
*
18+
* Implement the MKAverage class:
19+
*
20+
* MKAverage(int m, int k) Initializes the MKAverage object with an empty stream and the two
21+
* integers m and k.
22+
* void addElement(int num) Inserts a new element num into the stream.
23+
* int calculateMKAverage() Calculates and returns the MKAverage for the current stream
24+
* rounded down to the nearest integer.
25+
*
26+
* Example 1:
27+
*
28+
* Input
29+
* ["MKAverage", "addElement", "addElement", "calculateMKAverage", "addElement", "calculateMKAverage",
30+
* "addElement", "addElement", "addElement", "calculateMKAverage"]
31+
* [[3, 1], [3], [1], [], [10], [], [5], [5], [5], []]
32+
* Output
33+
* [null, null, null, -1, null, 3, null, null, null, 5]
34+
*
35+
* Explanation
36+
* MKAverage obj = new MKAverage(3, 1);
37+
* obj.addElement(3); // current elements are [3]
38+
* obj.addElement(1); // current elements are [3,1]
39+
* obj.calculateMKAverage(); // return -1, because m = 3 and only 2 elements exist.
40+
* obj.addElement(10); // current elements are [3,1,10]
41+
* obj.calculateMKAverage(); // The last 3 elements are [3,1,10].
42+
* // After removing smallest and largest 1 element the container will be
43+
* [3].
44+
* // The average of [3] equals 3/1 = 3, return 3
45+
* obj.addElement(5); // current elements are [3,1,10,5]
46+
* obj.addElement(5); // current elements are [3,1,10,5,5]
47+
* obj.addElement(5); // current elements are [3,1,10,5,5,5]
48+
* obj.calculateMKAverage(); // The last 3 elements are [5,5,5].
49+
* // After removing smallest and largest 1 element the container will be
50+
* [5].
51+
* // The average of [5] equals 5/1 = 5, return 5
52+
*
53+
* Constraints:
54+
*
55+
* 3 <= m <= 10^5
56+
* 1 <= k*2 < m
57+
* 1 <= num <= 10^5
58+
* At most 10^5 calls will be made to addElement and calculateMKAverage.
59+
******************************************************************************************************/
60+
61+
class MKAverage {
62+
private:
63+
vector<int> ringBuf;
64+
int pos;
65+
multiset<int> left, mid, right;
66+
long sum;
67+
long maxmin;
68+
int m;
69+
int k;
70+
private:
71+
template <class T>
72+
void print(T& v) {
73+
for(auto it : v){
74+
cout << it << "+";
75+
}
76+
cout <<endl;
77+
}
78+
int takeMax(multiset<int>& s) {
79+
auto it = --s.end();
80+
int n = *it;
81+
s.erase(it);
82+
return n;
83+
}
84+
int takeMin(multiset<int>& s) {
85+
auto it = s.begin();
86+
int n = *it;
87+
s.erase(it);
88+
return n;
89+
}
90+
public:
91+
MKAverage(int _m, int _k): ring(_m, 0), m(_m), k(_k), sum(0), pos(0), maxmin(0) {
92+
93+
}
94+
95+
void ins(int n) {
96+
left.insert(n);
97+
maxmin += n;
98+
if (left.size() > k ) {
99+
int n = takeMax(left);
100+
right.insert(n);
101+
if (right.size() > k) {
102+
int n = takeMin(right);
103+
maxmin -= n;
104+
mid.insert(n);
105+
}
106+
}
107+
}
108+
109+
void del(int n) {
110+
if (n <= *(left.rbegin())) {
111+
left.erase(left.find(n));
112+
int n1 = takeMin(mid);
113+
left.insert(n1);
114+
maxmin += (n1 - n);
115+
}else if (n >= *(right.begin())) {
116+
right.erase(right.find(n));
117+
int n1 = takeMax(mid);
118+
right.insert(n1);
119+
maxmin += (n1 - n);
120+
}else {
121+
mid.erase(mid.find(n));
122+
}
123+
}
124+
125+
void addElement(int num) {
126+
pos++;
127+
if (pos > m) {
128+
int n = ringBuf[pos % m];
129+
sum -= n;
130+
del(n);
131+
//cout << "DEL: n=" << n << ", sum=" << sum << ", maxmin=" << maxmin << endl;
132+
//print(left); print(mid);print(right);
133+
}
134+
135+
ringBuf[pos % m] = num ;
136+
sum += num;
137+
138+
ins(num);
139+
//cout << "INS: n=" << num << ", sum=" << sum << ", maxmin=" << maxmin << endl;
140+
//print(left); print(mid);print(right);
141+
}
142+
143+
144+
int calculateMKAverage() {
145+
if (pos < m) return -1;
146+
//cout << "CAL: sum=" << sum << ", maxmin=" << maxmin << ", delta=" << sum - maxmin<< endl;
147+
return (sum - maxmin) / (m-2*k);
148+
}
149+
};
150+
151+
/**
152+
* Your MKAverage object will be instantiated and called as such:
153+
* MKAverage* obj = new MKAverage(m, k);
154+
* obj->addElement(num);
155+
* int param_2 = obj->calculateMKAverage();
156+
*/
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
//TLE solution - using only one array and Binary Search.
167+
168+
169+
class MKAverage1 {
170+
private:
171+
vector<int> ring;
172+
int pos;
173+
vector<int> sort;
174+
long sum;
175+
long maxmin;
176+
int m;
177+
int k;
178+
private:
179+
template <class T>
180+
void print(T& v) {
181+
for(auto it : v){
182+
cout << it << "+";
183+
}
184+
cout <<endl;
185+
}
186+
public:
187+
MKAverage1(int _m, int _k): ring(_m,0), m(_m), k(_k), sum(0), pos(0), maxmin(0) {
188+
189+
}
190+
void ins(int n) {
191+
192+
int low = 0, high = sort.size()-1;
193+
int mid;
194+
if (high < 0 || n >= sort[high]) {
195+
sort.push_back(n);
196+
return;
197+
}
198+
199+
while(low <= high){
200+
mid = low + (high-low)/2;
201+
if (sort[mid] <= n ) low = mid + 1;
202+
else high = mid - 1;
203+
}
204+
auto it = sort.begin() + low;
205+
sort.insert(it, n);
206+
}
207+
208+
void del(int n) {
209+
int len = sort.size();
210+
int low = 0, high = len -1;
211+
int mid;
212+
while(low <= high){
213+
mid = low + (high-low)/2;
214+
if (sort[mid] == n) break;
215+
if (sort[mid] < n ) low = mid + 1;
216+
else high = mid - 1;
217+
}
218+
219+
if (low > high) return;
220+
221+
auto it = sort.begin() + mid;
222+
sort.erase(it);
223+
224+
}
225+
void addElement(int num) {
226+
pos++;
227+
228+
if (pos > m) {
229+
int n = ring[pos % m];
230+
sum -= n;
231+
232+
int len = sort.size();
233+
if (n <= sort[k-1] ) maxmin += (sort[k]-n);
234+
else if (n >= sort[len-k]) maxmin += (sort[len-k-1] - n);
235+
236+
del(n);
237+
//cout << "DEL: n=" << n << ", sum=" << sum << ", maxmin=" << maxmin << endl;
238+
//print(sort);
239+
}
240+
241+
242+
ring[pos % m] = num;
243+
sum += num;
244+
245+
if (sort.size() < 2*k ) {
246+
maxmin += num;
247+
} else {
248+
int len = sort.size();
249+
if (num <= sort[k-1]) maxmin += (num - sort[k-1]);
250+
else if (num >= sort[len-k]) maxmin += (num -sort[len-k]);
251+
}
252+
253+
ins(num);
254+
//cout << "INS: n=" << num << ", sum=" << sum << ", maxmin=" << maxmin << endl;
255+
//print(sort);
256+
}
257+
258+
259+
int calculateMKAverage() {
260+
if ( pos < m) return -1;
261+
//cout << "CAL: sum=" << sum << ", maxmin=" << maxmin << ", delta=" << sum - maxmin<< endl;
262+
return (sum - maxmin) / (m-2*k);
263+
}
264+
};
265+
266+
/**
267+
* Your MKAverage object will be instantiated and called as such:
268+
* MKAverage* obj = new MKAverage(m, k);
269+
* obj->addElement(num);
270+
* int param_2 = obj->calculateMKAverage();
271+
*/
272+
273+
274+
275+

0 commit comments

Comments
 (0)