LeetCode:239. 滑动窗口最大值 - 力扣(LeetCode)
1.思路
滑动窗口,暴力解法(超时) 双端队列,记录区间内最大值的索引,将索引对应的元素加入结果数组中,返回结果即可.
2.代码实现
// 暴力解法
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int maxcount = -100000;
int[] res = new int[nums.length-k+1];
int count = 0;
for (int i = 0; i < nums.length-k+1; i++) {
for (int j = i; j < i + k; j++) {
maxcount= Math.max(maxcount, nums[j]);
}
res[count++] = maxcount;
maxcount = -100000;
}
return res;
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
// 使用双端队列来存储滑动窗口中的元素索引
ArrayDeque<Integer> deque = new ArrayDeque<>();
int n = nums.length;
// 结果数组的长度为 n - k + 1
int[] res = new int[n - k + 1];
int idx = 0; // 结果数组的索引
for (int i = 0; i < n; i++) {
// 移除队列中已经不在滑动窗口范围内的元素
while (!deque.isEmpty() && deque.peek() < i - k + 1) {
deque.poll();
}
// 移除队列中比当前元素小的元素
while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {
deque.pollLast();
}
deque.offer(i); // 将当前元素索引加入队列
if (i >= k - 1) { // 当窗口的大小达到 k 时
res[idx++] = nums[deque.peek()]; // 将队列中的最大元素加入结果数组
}
}
return res; // 返回结果数组
}
}
3.复杂度分析
时间复杂度:O(n).
空间复杂度:O(k).
LeetCode:347. 前 K 个高频元素 - 力扣(LeetCode)
1.思路
使用map 中key-value结构做映射,value记录频率。 借助优先级队列,对其进行排序,维护频率前k高的元素。
2.代码实现
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 创建一个优先队列,按照频率升序排序
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
// 创建结果数组
int[] res = new int[k];
// 创建一个 HashMap 来存储元素和其对应的频率
Map<Integer, Integer> map = new HashMap<>();
// 遍历整数数组,统计元素的频率
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
// 遍历 HashMap 中的元素,将元素和频率放入优先队列中
for (var x : map.entrySet()) {
int[] tmp = new int[2];
tmp[0] = x.getKey(); // 元素
tmp[1] = x.getValue(); // 频率
pq.offer(tmp);
// 如果优先队列的大小超过 k,移除频率最小的元素
if (pq.size() > k) {
pq.poll();
}
}
// 从优先队列中取出前 k 个元素作为结果
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0];
}
return res;
}
}
import java.util.*;
class Solution {
public int[] topKFrequent(int[] nums, int k) {
// 创建一个优先队列,按照频率升序排序
PriorityQueue<int[]> pq = new PriorityQueue<>((o1, o2) -> o1[1] - o2[1]);
// 创建结果数组
int[] res = new int[k];
// 创建一个 HashMap 来存储元素和其对应的频率
Map<Integer, Integer> map = new HashMap<>();
// 遍历整数数组,统计元素的频率
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
}
// 遍历 HashMap 中的元素,将元素和频率放入优先队列中
Iterator<Map.Entry<Integer, Integer>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, Integer> entry = iterator.next();
int[] tmp = new int[2];
tmp[0] = entry.getKey(); // 元素
tmp[1] = entry.getValue(); // 频率
pq.offer(tmp);
// 如果优先队列的大小超过 k,移除频率最小的元素
if (pq.size() > k) {
pq.poll();
}
}
// 从优先队列中取出前 k 个元素作为结果
for (int i = 0; i < k; i++) {
res[i] = pq.poll()[0];
}
return res;
}
}
以上代码将增强for循环改为普通for循环,使用迭代器遍历 map 中的元素。在循环中,获取每个元素的键和值,并将它们放入优先队列 pq 中。如果优先队列的大小超过 k,移除频率最小的元素。最后,从优先队列中取出前 k 个元素作为结果数组 res 返回。
3.复杂度分析
时间复杂度:O(n).
空间复杂度:O(k).