先决条件:基于策略的数据结构,滑动窗口技术。
给定一个整数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)
Sorted Set 方法:参考数组中滑动窗口的中位数使用SortedSet解决问题。
有序集方法:
在本文中,使用基于策略的有序集数据结构解决问题的方法。
请按照以下步骤解决问题:
- 在 Ordered_set 中插入大小为 K的第一个窗口(维护排序顺序)。因此,此有序集合的中间元素是相应窗口所需的中值。
- 中间元素可以在 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 Classes Live