题目
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
思路
-
如果说自己可以实现一个队列,只要有3个功能
- poll()弹出首元素
- add()添加新元素
- peek()返回的首元素为最大值
-
队列实现
- 入队元素,与入队口元素相比,比入队口元素大,移除入队口元素之后,再添加,比如:[-1,2,3] 入队,结果是 -1;2;3,最终队列中只剩3
- 元素出队,需要判断一下元素是不是对首元素,因为之前入队的时候元素可能已经被移除了
- 这样,队列中每出队,入队一个元素,对首的元素总为窗口最大值
代码实现
public class WindowsMaxValue {
public int[] getWindowsMaxValue(int [] windows, int k){
int length = windows.length;
if(windows.length==1){
return windows;
}
int [] result = new int[length-k+1];
int index =0;
myQueue queue =new myQueue();
//k之前的元素先入队
for (int i=0; i<k; i++) {
queue.add(windows[i]);
}
//第一个窗口的最大值
result[index++] = queue.peek();
for (int i=k; i<length; i++) {
//窗口开始移动,首元素出队,信元素入队
queue.poll(windows[k-i]);
queue.add(windows[i]);
//每个窗口的最大值
result[index++] = queue.peek();
}
return result;
}
private static class myQueue{
Deque<Integer> queue = new LinkedList<Integer>();
void add(int value){
//对首元素出队,要判断队首元素是不是要出的元素
while (!queue.isEmpty()&& queue.getLast()<value){
queue.removeLast();
}
queue.add(value);
}
void poll(int value){
//只要存在比入队元素小的元素,就要移除
if(!queue.isEmpty() && queue.peek()==value){
queue.poll();
}
}
Integer peek(){
return queue.peek();
}
}
}
题目
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例1
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例2
输入: nums = [1], k = 1
输出: [1]
思路
- 前 K 个高频元素
- 先统计元素出现的频次,用map存储 元素->频次
- 将二元组依次放入大顶堆
- 然后从大顶堆一次弹出二元组的首元素,放入数组,即为结果
代码实现
public int [] getTopK(int [] nums, int k){
Map<Integer,Integer> map = new HashMap<>();
for (int i = 0; i < nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
//定义大顶堆
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair2[1]-pair1[1]);
for (Map.Entry<Integer,Integer> entry : map.entrySet()){
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
int[] result = new int[k];
for (int i = 0; i < k ; i++){
result[i] = pq.poll()[0];
}
return result;
}