480. 滑动窗口中位数
中位数是有序序列最中间的那个数。如果序列的大小是偶数,则没有最中间的数;此时中位数是最中间的两个数的平均数。
例如:
[2,3,4]
,中位数是3
[2,3]
,中位数是(2 + 3) / 2 = 2.5
给你一个数组 nums,有一个大小为 k 的窗口从最左端滑动到最右端。窗口中有 k 个数,每次窗口向右移动 1 位。你的任务是找出每次窗口移动后得到的新窗口中元素的中位数,并输出由它们组成的数组。
示例:
给出 nums = [1,3,-1,-3,5,3,6,7]
,以及 k = 3。
窗口位置 中位数 --------------- ----- [1 3 -1] -3 5 3 6 7 1 1 [3 -1 -3] 5 3 6 7 -1 1 3 [-1 -3 5] 3 6 7 -1 1 3 -1 [-3 5 3] 6 7 3 1 3 -1 -3 [5 3 6] 7 5 1 3 -1 -3 5 [3 6 7] 6
因此,返回该滑动窗口的中位数数组 [1,-1,-1,3,5,6]
。
提示:
- 你可以假设
k
始终有效,即:k
始终小于输入的非空数组的元素个数。 - 与真实值误差在
10 ^ -5
以内的答案将被视作正确答案。
我的Java代码:
思路:所给的数组是无序的,题目所指的窗口中的中位数是要把窗口内的元素排序后的中位数。所以用双指针来维护滑动窗口,并且将窗口内的元素转移到列表中进行排序,然后取中位数。移动窗口的时候将移动的左端元素从列表中移除,再添加右端元素进列表。这种方法效率较低,改进排序方法应该会好一些,可以考虑用冒泡排序。
class Solution {
public static double[] medianSlidingWindow(int[] nums, int k) {
int len = nums.length;
double[] result = new double[len-k+1];
int r = 0;
int head = 0, rear = k;
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i = head;i < rear-1;i++) {
list.add(nums[i]);
}
while(rear <= len) {
list.add(nums[rear-1]);
Collections.sort(list);
if(k%2 != 0) {
result[r] = list.get(k/2);
}else {
result[r] = ((double)list.get(k/2-1)+(double)list.get(k/2))/2;
}
r++;
int i = list.indexOf(nums[head]);
list.remove(i);
rear++;
head++;
}
return result;
}
}