滑动窗口中位数
难度:
标签:
题目描述
The median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle values.
- For examples, if
arr = [2,3,4]
, the median is3
. - For examples, if
arr = [1,2,3,4]
, the median is(2 + 3) / 2 = 2.5
.
You are given an integer array nums
and an integer k
. There is a sliding window of size k
which is moving from the very left of the array to the very right. You can only see the k
numbers in the window. Each time the sliding window moves right by one position.
Return the median array for each window in the original array. Answers within 10-5
of the actual value will be accepted.
Example 1:
Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 Output: [1.00000,-1.00000,-1.00000,3.00000,5.00000,6.00000] Explanation: Window position Median --------------- ----- [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
Example 2:
Input: nums = [1,2,3,4,2,3,1,4,2], k = 3 Output: [2.00000,3.00000,3.00000,3.00000,2.00000,3.00000,2.00000]
Constraints:
1 <= k <= nums.length <= 105
-231 <= nums[i] <= 231 - 1
代码结果
运行时间: 145 ms, 内存: 30.0 MB
/*
* 题目思路:
* 1. 我们需要找到每个窗口的中位数。
* 2. 使用双优先队列,一个最大堆,一个最小堆。
* 3. 最大堆存储较小的一半元素,最小堆存储较大的一半元素。
* 4. 当滑动窗口移动时,添加新元素并删除旧元素,保持两个堆的平衡。
* 5. 如果k是奇数,中位数是最大堆的堆顶;如果k是偶数,中位数是两个堆顶的平均值。
*/
import java.util.*;
import java.util.stream.*;
public class SlidingWindowMedianStream {
public double[] medianSlidingWindow(int[] nums, int k) {
return IntStream.range(0, nums.length - k + 1)
.mapToDouble(i -> findMedian(Arrays.stream(nums, i, i + k).sorted().toArray(), k))
.toArray();
}
private double findMedian(int[] window, int k) {
if (k % 2 == 0) {
return ((double) window[k / 2 - 1] + window[k / 2]) / 2;
} else {
return window[k / 2];
}
}
}
解释
方法:
时间复杂度:
空间复杂度:
代码细节讲解
相关问题
数据流的中位数
中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
- 例如
arr = [2,3,4]
的中位数是3
。 - 例如
arr = [2,3]
的中位数是(2 + 3) / 2 = 2.5
。
实现 MedianFinder 类:
-
MedianFinder()
初始化MedianFinder
对象。 -
void addNum(int num)
将数据流中的整数num
添加到数据结构中。 -
double findMedian()
返回到目前为止所有元素的中位数。与实际答案相差10-5
以内的答案将被接受。
示例 1:
输入 ["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"] [[], [1], [2], [], [3], []] 输出 [null, null, null, 1.5, null, 2.0] 解释 MedianFinder medianFinder = new MedianFinder(); medianFinder.addNum(1); // arr = [1] medianFinder.addNum(2); // arr = [1, 2] medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2) medianFinder.addNum(3); // arr[1, 2, 3] medianFinder.findMedian(); // return 2.0
提示:
-105 <= num <= 105
- 在调用
findMedian
之前,数据结构中至少有一个元素 - 最多
5 * 104
次调用addNum
和findMedian