leetcode:239. 滑動視窗最大值 - 力扣(LeetCode)
思路:看了挺長時間才反應過來與暴力演算法的區別。當遇到比上一個元素大的值時,將上一個元素剔除,小於時加入佇列中,每次等於視窗長度時將頂端也就是最大值存起來
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int[] res =new int[nums.length - k + 1]; ArrayDeque<Integer> deque = new ArrayDeque() ; int index = 0; for(int i = 0; i < nums.length; i++){ //這個判斷的是超出界限,超出就要將頂端刪除 while( !deque.isEmpty() && deque.peek() < i - k +1){ deque.poll(); } //清除雙端佇列中小於當前元素的索引,以保證佇列中元素按照降序排列,peeklast對應的是最大值的下標,當[i]大於最大值就把最大值彈出。 while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]){ deque.pollLast(); } //存。 deque.offer(i); //當視窗大小等於k時,存進去。 if(i >= k - 1){ res[index++] = nums[deque.peek()]; } } return res; } }
leetcode:347. 前 K 個高頻元素 - 力扣(LeetCode)
思路:看起來可以用hashmap,和那個統計出現最多那個有點相同,但是時間有限制。
思路很簡單,主要是優先順序佇列,大頂堆,小頂堆不知道...
class Solution { public int[] topKFrequent(int[] nums, int k) { // 優先順序佇列,為了避免複雜 api 操作,pq 儲存陣列 // lambda 表示式設定優先順序佇列從大到小儲存 o1 - o2 為從小到大,o2 - o1 反之 PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]); int[] res = new int[k]; // 答案陣列為 k 個元素 Map<Integer, Integer> map = new HashMap<>(); // 記錄元素出現次數 for(int num : nums) map.put(num, map.getOrDefault(num, 0) + 1); for(var x : map.entrySet()) { // entrySet 獲取 k-v Set 集合 // 將 kv 轉化成陣列 int[] tmp = new int[2]; tmp[0] = x.getKey(); tmp[1] = x.getValue(); pq.offer(tmp); // 下面的程式碼是根據小根堆實現的,我只保留優先佇列的最後的k個,只要超出了k我就將最小的彈出,剩餘的k個就是答案 if(pq.size() > k) { pq.poll(); } } for(int i = 0; i < k; i ++) { res[i] = pq.poll()[0]; // 獲取優先佇列裡的元素 } return res; } }
晚上解決一下優先順序佇列的問題。,樹有點東西的
優先順序佇列,用來尋找最大值或最小值,使用了二叉樹原理,堆排序。插入資料,新增資料的時間複雜度都是logn,感覺挺有意思,