先决条件:基于策略的数据结构,滑动窗口技术。
给定一个由整数arr []和一个整数K组成的数组,任务是找到大小为K的每个窗口的中值,该窗口的大小从左开始,每次向右移动一个位置。
例子:
Input: arr[] = {-1, 5, 13, 8, 2, 3, 3, 1}, K = 3
Output: 5 8 8 3 3 3
Explanation:
1st Window: {-1, 5, 13} Median = 5
2nd Window: {5, 13, 8} Median = 8
3rd Window: {13, 8, 2} Median = 8
4th Window: {8, 2, 3} Median = 3
5th Window: {2, 3, 3} Median = 3
6th Window: {3, 3, 1} Median = 3
Input: arr[] = {-1, 5, 13, 8, 2, 3, 3, 1}, K = 4
Output: 6.5 6.5 5.5 3.0 2.5
天真的方法:
解决该问题的最简单方法是遍历每个大小为K的窗口,并对窗口的元素进行排序,然后找到中间元素。将每个窗口的中间元素打印为中间值。
时间复杂度: O(N * KlogK)
辅助空间: O(K)
排序集方法:请参阅数组中滑动窗口的中位数以使用SortedSet解决问题。
有序集方法:
本文提供了一种使用基于策略的有序集数据结构解决问题的方法。
请按照以下步骤解决问题:
- 将第一个大小为K的窗口插入Ordered_set(保持排序顺序)。因此,此有序集合的中间元素是相应窗口的所需中间值。
- 中间元素可以通过O(logN)计算复杂度的find_by_order()方法获得。
- 通过删除上一个窗口的第一个元素并插入新元素,进入以下窗口。要从集合中删除任何元素,请使用order_by_key()在Ordered_Set中查找元素的顺序,以O(logN)的计算复杂度获取结果,然后通过使用find_by_order在Ordered_Set中搜索其获得的顺序来擦除该元素()方法。现在,为新窗口添加新元素。
- 对每个窗口重复上述步骤,并打印相应的中位数。
下面是上述方法的实现。
CPP
// C++ Program to implement the
// above approach
#include
#include
using namespace std;
using namespace __gnu_pbds;
// Policy based data structure
typedef tree, rb_tree_tag,
tree_order_statistics_node_update>
Ordered_set;
// Function to find and return the
// median of every window of size k
void findMedian(int arr[], int n,
int k)
{
Ordered_set s;
for (int i = 0; i < k; i++)
s.insert(arr[i]);
if (k & 1) {
// Value at index k/2
// in sorted list.
int ans = *s.find_by_order(k / 2);
cout << ans << " ";
for (int i = 0; i < n - k; i++) {
// Erasing Element out of window.
s.erase(s.find_by_order(
s.order_of_key(
arr[i])));
// Inserting newer element
// to the window
s.insert(arr[i + k]);
// Value at index k/2 in
// sorted list.
ans = *s.find_by_order(k / 2);
cout << ans << " ";
}
cout << endl;
}
else {
// Getting the two middle
// median of sorted list.
float ans = ((float)*s.find_by_order(
(k + 1) / 2 - 1)
+ (float)*s.find_by_order(k
/ 2))
/ 2;
printf("%.2f ", ans);
for (int i = 0; i < n - k; i++) {
s.erase(s.find_by_order(
s.order_of_key(arr[i])));
s.insert(arr[i + k]);
ans = ((float)*s.find_by_order(
(k + 1) / 2 - 1)
+ (float)*s.find_by_order(k
/ 2))
/ 2;
printf("%.2f ", ans);
}
cout << endl;
}
}
// Driver Code
int main()
{
int arr[] = { -1, 5, 13, 8, 2,
3, 3, 1 };
int k = 3;
int n = sizeof(arr)
/ sizeof(arr[0]);
findMedian(arr, n, k);
return 0;
}
5 8 8 3 3 3
时间复杂度: O(NlogK)
辅助空间: O(K)
如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。