239. Sliding Window Maximum
- 思路
- 有点难
- 遍历数组,存到deque里
- 如果遍历到的数比deque里最后一个数大 —>poll()
- 如此在滑动到index= k-1时,deque.peek()就是最大数
- 如果遍历到的数比deque里最后一个数大 —>poll()
- 遍历数组,存到deque里
-
java class Solution { public int[] maxSlidingWindow(int[] nums, int k) { ArrayDeque deque = new ArrayDeque<>(); int n = nums.length; int[] res = new int[n- k + 1]; int idx = 0; for(int i = 0; i < n; i++){ // 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点 // 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出 while(!deque.isEmpty() && deque.peek() < i - k + 1){ deque.poll(); } // 2.既然是单调,就要保证每次放进去的数字要比末尾的都大,否则也弹出 while(!deque.isEmpty()&& nums[deque.peekLast()] < nums[i]){ deque.pollLast(); } deque.offer(i); // 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了 if(i >=k -1){ res[idx++] = nums[deque.peek()]; } } return res; } }
347. Top K Frequent Elements
- 思路
- 基于大小顶堆
- 基于小顶堆: NLOGK由于只维护K个元素
-
java class Solution { //基于小顶堆实现 public int[] topKFrequent(int[] nums, int k) { Map map = new HashMap<>(); for(int num : nums){ map.put(num, map.getOrDefault(num, 0) + 1); } //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数 //出现次数按从队头到队尾的顺序是从小到大排,出现次数最低的在队头(相当于小顶堆) PriorityQueue pq = new PriorityQueue<>((pair1,pair2)->pair1[1] - pair2[1]); for(Map.Entry entry : map.entrySet()){ //小顶堆只需要维持k个元素有序 //小顶堆元素个数小于k个时直接加 if(pq.size() < k){ pq.add(new int[]{entry.getKey(), entry.getValue()}); }else{ //当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个) if(entry.getValue()> pq.peek()[1]){ pq.poll(); pq.add(new int[]{entry.getKey(), entry.getValue()}); } } } //依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多 int[] ans = new int[k]; for(int i = k -1; i >=0; i--){ ans[i] = pq.poll()[0]; } return ans; } }
-
- 基于大顶: TC NLOGN
- 思路与小顶堆差不多,但由于大顶堆是全部存完之后pop头上K个元素,所以要维护所有的元素,为NLOGN
- 基于小顶堆: NLOGK由于只维护K个元素
- 基于大小顶堆