day12
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 最大值 --------------- ----- [1 3 -1] -3 5 3 6 7 3 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 5 1 3 -1 -3 [5 3 6] 7 6 1 3 -1 -3 5 [3 6 7] 7
暴力破解:每运动一次都遍历窗口里面的数字...显然不现实。
最小栈思路:
用最小栈作为窗口:由栈尾到栈口的元素是依次减小(或相等)的
当栈每一次滑动的时候,都会进入一个元素m,对m进行判断处理:当m小于等于栈口元素就直接将其添加到栈中当m大于栈口元素时,循环将栈口元素弹出,直到栈口元素大于m或栈为空,当窗口的元素个数等于k个后栈尾的元素为当前窗口的最大值。
当栈的元素等于k后,每次滑动还要弹出栈尾的一个元素,但是为了维护最小栈,栈内的元素可能不足k个,这时我们可以使用判断当前栈尾的元素是否为当前加入元素索引的前k个索引元素,如果是就先将其弹出,在进行加入元素操作。
模拟:
输入:nums = [1,3,3,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7] 解释: 滑动窗口的位置 栈内元素 最大值 [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 [3 -1] 3 1 [3 -1 -3] 5 3 6 7 [3 -1 -3] 3 1 3 [-1 -3 5] 3 6 7 [5] 5 1 3 -1 [-3 5 3] 6 7 [5 3] 5 1 3 -1 -3 [5 3 6] 7 [6] 6 1 3 -1 -3 5 [3 6 7] [7] 7
当新加入一个元素m的时候:
如果比栈口的元素大,那么就可以将栈口元素弹出,因为m一定比栈口的元素索引靠后,也可以说有m在,栈口比其小的元素都不可能是窗口最大元素
如果比栈口的元素小或等于栈口元素,我们可以直接添加到栈中,因为虽然m小或等于,但是其索引靠后,可能当栈口元素因为窗口大小而弹出栈的后,m就是最大的元素。
当弹出一个元素m的时候:
因为最小栈原理:由上面的加入元素可知,栈尾到栈口的元素一定是索引有小到大,元素有大到小,所以判断当前加入元素的前个元素m是否为栈尾元素,如果是就弹出,如果不是说明在当前窗口内有比m更大的元素n,在n加入到栈时就将m给弹出了。
代码实现
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
LinkedList<Integer> minList = new LinkedList<>();
int len = nums.length;
int[] res = new int[len-k+1];
int index = 0;
//处理窗口内元素不足k个
for(int i = 0; i < k; i++){
while(!minList.isEmpty() && minList.peekLast() < nums[i]){
minList.pollLast();
}
minList.add(nums[i]);
}
res[index++] = minList.peekFirst();
int pre = k;
while(k < len){
//弹出元素
if(minList.peekFirst() == nums[k - pre]) minList.pollFirst();
while(!minList.isEmpty() && minList.peekLast() < nums[k]){
minList.pollLast();
}
minList.add(nums[k]);
res[index++] = minList.peekFirst();
k++;
}
return res;
}
}
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
思路:使用哈希表存储数组内不同数字的出现个数
使用int数组类型优先级队列:队列存储的数组存有两个元素,第一个为数组内的数字,第二个为该数字出现的次数,优先队列的排序规则为数字出现次数越多的越靠后
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
Queue<int[]> queue = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if(queue.size() == k){
int[] remove = queue.remove();
if(entry.getValue() > remove[1]){
queue.add(new int[]{entry.getKey(),entry.getValue()});
}else{
queue.add(remove);
}
}else{
queue.add(new int[]{entry.getKey(), entry.getValue()});
}
}
int[] res = new int[k--];
for (int[] ints : queue) {
res[k--] = ints[0];
}
return res;
}
}