给定两个正整数N和K ,初始化一个空数组arr[]和Q个以下两种类型的查询:
- addInteger(x):在数组arr[] 中插入元素X。如果数组的大小变得大于N ,则从数组的开头删除元素。
- calculateSpecialAverage():在去掉前K个最小和最大元素后求数组元素的平均值。如果数组的大小 小于N ,然后打印-1 。
任务是处理给定的查询并相应地打印结果。
例子:
Input: N = 3, K = 1, Q = 5, Queries[] = { addInteger(4), addInteger(2), calculateSpecialAverage(), addInteger(10), calculateSpecialAverage() }
Output: -1, 4
Explanation:
Below are the queries performed:
Query 1 is to insert element 4 in the array, arr[] becomes {4}.
Query 2 is to insert the element 2 in the array, arr[] becomes {4, 2}.
Query 3 is to find the average. Since the size of the array is less than N(= 3), print -1.
Query 4 is to insert the element 10 in the array, arr[] becomes {4, 2, 10}.
Query 5 is to find the average. Since the size of the array =3, remove K(= 1) the smallest element i.e., 2 and then remove the largest element i.e., 10. Now the average will be 4/1 = 4.
Input: N = 3, K = 1, Q = 5, Queries[] = { addInteger(4), addInteger(21), calculateSpecialAverage() }
Output: -1
方法:给定的问题可以通过使用多重集来解决。请按照以下步骤解决问题:
- 初始化左、右和中三个多重集以存储K 个最小、 K 个最大和剩余的(N – 2*K) 个整数。
- 声明一个大小为N的向量v来存储最后N 个整数。
- 声明一个整数变量pos来跟踪当前索引和一个整数和来存储中间多集中值的总和,这是计算(N – 2*K) 个整数的平均值所需的总和。
- 定义一个函数add以根据其值在左、中或右多重集中插入一个整数。要在正确的多重集中插入整数,请执行以下步骤:
- 最初,将整数插入左多重集中。
- 如果左侧多重集的大小超过k ,则从左侧多重集中删除最大的整数并将其插入中间多重集。
- 如果mid multiset 的大小超过(n – 2*k) ,则从mid multiset 中删除最大的整数并将其插入到正确的multiset 中。
- 在中间多重集中删除和添加整数时保持正确的sum值,即如果从中间多重集中删除一个整数,则从总和中减去它的值,类似地,如果在中间多重集中添加一个整数,将其值添加到sum ,以保持更新的总和值。
- 声明一个函数remove以从左、右或中间多重集擦除整数。
- 如果整数num 的值小于或等于左侧多重集中的最大整数,则从左侧多重集中查找并删除该整数,否则根据其值在中间或右侧多重集中搜索它。
- 如果删除num 后,大小 左边的多重集减少,从中删除最小的整数 中间多组并将其插入 左多重集。
- 同理,对于mid multiset,如果size变小了,删除最小的整数 正确的多重集并将其插入 中间多组。
- 定义一个函数addInteger向当前流添加一个整数:
- 如果当前流中的整数数量(左、中、右多重集的大小之和)超过n ,则删除索引pos%n处的整数。
- 调用函数add插入整数 左、中或右多重集,基于其值。
- 定义函数calculateSpecialAverage以返回特殊平均值:
- 如果流中的整数数小于N ,则打印-1 。
- 否则,将平均值打印为(sum/(N – 2*K)) 。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Special Average class
class SpecialAverage {
public:
// Three multisets to store the
// smaller K larger K and the
// remaining (n-2*k) integers
multiset left, mid, right;
int n, k;
// Stores the index of current
// integer in running stream of
// integers and the sum of integers
// in mid multiset
long pos, sum;
// Array to store last n integers
vector v;
// Constructor to initialize the
// values of n and k and initialize
// default values
SpecialAverage(int nvalue, int kvalue)
{
n = nvalue;
k = kvalue;
pos = 0;
sum = 0;
for (int i = 0; i < n; i++)
v.push_back(0);
}
// Add current integer in the
// multiset left, mid or right
// based on its value
void add(int num)
{
// Firstly, insert num in the
// left multiset
left.insert(num);
// Check if size of the left
// multiset is greater than k
if (left.size() > k) {
// Stores the value of the
// largest integer in the
// left multiset
int temp = *(prev(end(left)));
// Insert temp in the
// mid multiset
mid.insert(temp);
// Remove temp from the
// left multiset
left.erase(prev(end(left)));
// Add the value of temp
// to the current sum
sum += temp;
}
// Check if the size of mid
// multiset exceeds (n-2*k)
if (mid.size() > (n - 2 * k)) {
// Stores the value of the
// largest integer in the
// mid multiset
int temp = *(prev(end(mid)));
// Insert temp in the
// right multiset
right.insert(temp);
// Remove temp from the
// mid multiset
mid.erase(prev(end(mid)));
// Subtract the value of
// temp from current sum
sum -= temp;
}
}
// Remove integer from the
// multiset left, mid or right
// based on its value
void remove(int ele)
{
// If integer exists in the
// left multiset
if (ele <= *(left.rbegin()))
left.erase(left.find(ele));
// If integer exists in the
// mid multiset
else if (ele <= *(mid.rbegin())) {
// Subtract the value of
// integer from current sum
sum -= ele;
mid.erase(mid.find(ele));
}
// If integer exists in the
// right multiset
else
right.erase(right.find(ele));
// Balance all the multisets
// left, right and mid check
// if size of the left multiset
// is less than k
if (left.size() < k) {
// Stores the value of
// smallest integer
// in mid multiset
int temp = *(mid.begin());
// Insert temp in the
// left multiset
left.insert(temp);
// Remove temp from the
// mid multiset
mid.erase(mid.begin());
// Subtract the value of
// temp from current sum
sum -= temp;
}
// Check if the size of mid
// multiset becomes lesser
// than (n-2*k)
if (mid.size() < (n - 2 * k)) {
// Stores the value of
// smallest integer in
// right multiset
int temp = *(right.begin());
// Insert temp in the
// mid multiset
mid.insert(temp);
// Remove temp from the
// right multiset
right.erase(right.begin());
// Add the value of temp
// to the current sum
sum += temp;
}
}
// Function to add integer to
// the current stream
void addInteger(int num)
{
// Check if the total number
// of elements in stream > n
if (pos >= n)
// Call the function to
// remove extra integer
remove(v[pos % n]);
// Insert the current integer
// in the array v
v[(pos++) % n] = num;
// Call the function to add
// the current integer in left,
// mid or right multiset
// based on its value
add(num);
}
// Function to calculate the
// special average
int calculateSpecialAverage()
{
// Check if the total number
// of elements is greater than
// or equal to n
if (pos >= n)
// Return desired average
return ((double)sum) / (n - 2 * k);
return -1;
}
};
// Function to process all the queries
void processQueries(int n, int k)
{
// Create an object of the class
SpecialAverage* avg
= new SpecialAverage(n, k);
// Add integer Query
avg->addInteger(4);
avg->addInteger(2);
// Find average Query
cout << avg->calculateSpecialAverage()
<< endl;
// Add integer Query
avg->addInteger(10);
// Find average Query
cout << avg->calculateSpecialAverage()
<< endl;
}
// Driver Code
int main()
{
int N = 3, K = 1;
processQueries(N, K);
return 0;
}
-1
4
时间复杂度: O(log N) for addInteger()和 O(1) for calculateSpecialAverage()
辅助空间: O(N)