leecode更新
This commit is contained in:
parent
26376573fb
commit
9afc59fc65
|
|
@ -165,7 +165,7 @@ public class MaxSlidingWindow {
|
||||||
/**
|
/**
|
||||||
* 官方使用优先队列完成的做法:时间复杂度O(nlogn)
|
* 官方使用优先队列完成的做法:时间复杂度O(nlogn)
|
||||||
* 对于「最大值」,我们可以想到一种非常合适的数据结构,那就是优先队列(堆),其中的大根堆可以帮助我们实时维护一系列元素中的最大值。
|
* 对于「最大值」,我们可以想到一种非常合适的数据结构,那就是优先队列(堆),其中的大根堆可以帮助我们实时维护一系列元素中的最大值。
|
||||||
* 对于本题而言,初始时,我们将数组 nums 的前 kk 个元素放入优先队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入优先队列中,此时堆顶的元素就是堆中所有元素的最大值。然而这个最大值可能并不在滑动窗口中,在这种情况下,这个值在数组 nums 中的位置出现在滑动窗口左边界的左侧。因此,当我们后续继续向右移动窗口时,这个值就永远不可能出现在滑动窗口中了,我们可以将其永久地从优先队列中移除。
|
* 对于本题而言,初始时,我们将数组 nums 的前 k 个元素放入优先队列中。每当我们向右移动窗口时,我们就可以把一个新的元素放入优先队列中,此时堆顶的元素就是堆中所有元素的最大值。然而这个最大值可能并不在滑动窗口中,在这种情况下,这个值在数组 nums 中的位置出现在滑动窗口左边界的左侧。因此,当我们后续继续向右移动窗口时,这个值就永远不可能出现在滑动窗口中了,我们可以将其永久地从优先队列中移除。
|
||||||
* 我们不断地移除堆顶的元素,直到其确实出现在滑动窗口中。此时,堆顶元素就是滑动窗口中的最大值。为了方便判断堆顶元素与滑动窗口的位置关系,我们可以在优先队列中存储二元组(num,index),表示元素 num 在数组中的下标为 index。
|
* 我们不断地移除堆顶的元素,直到其确实出现在滑动窗口中。此时,堆顶元素就是滑动窗口中的最大值。为了方便判断堆顶元素与滑动窗口的位置关系,我们可以在优先队列中存储二元组(num,index),表示元素 num 在数组中的下标为 index。
|
||||||
* <p>
|
* <p>
|
||||||
* TODO 本质上就是维护一个可以比较大小的优先队列,队列中存放(值,索引)
|
* TODO 本质上就是维护一个可以比较大小的优先队列,队列中存放(值,索引)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.markilue.leecode.stackAndDeque;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @BelongsProject: Leecode
|
||||||
|
* @BelongsPackage: com.markilue.leecode.stackAndDeque
|
||||||
|
* @Author: dingjiawen
|
||||||
|
* @CreateTime: 2022-09-16 09:24
|
||||||
|
* @Description: TODO 力扣347题 前k个高频元素
|
||||||
|
* 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
|
||||||
|
* @Version: 1.0
|
||||||
|
*/
|
||||||
|
public class TopKFrequent {
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
int[] nums = {1, 1, 1, 2, 2, 3};
|
||||||
|
int k = 2;
|
||||||
|
int[] result = topKFrequent1(nums, k);
|
||||||
|
System.out.println(Arrays.toString(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test1() {
|
||||||
|
int[] nums = {1};
|
||||||
|
int k = 1;
|
||||||
|
int[] result = topKFrequent(nums, k);
|
||||||
|
System.out.println(Arrays.toString(result));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自己的思路一:先给nums排序,那么相同的数一定在临近,然后遍历一遍获取count, ->如果使用数组进行记录则数组大小跟nums里最大的数有关,这里使用优先队列进行记录
|
||||||
|
* 整体时间复杂度O(nlogn),因为排序O(nlogn),遍历一遍O(n),放入优先队列O(logn)
|
||||||
|
* 速度击败99.59%,内存击败13.35%
|
||||||
|
*
|
||||||
|
* @param nums
|
||||||
|
* @param k
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int[] topKFrequent(int[] nums, int k) {
|
||||||
|
|
||||||
|
Arrays.sort(nums);
|
||||||
|
|
||||||
|
int lastNum = nums[0];
|
||||||
|
int count = 0;
|
||||||
|
//使用优先队列记录<num,count>
|
||||||
|
PriorityQueue<int[]> deque = new PriorityQueue<>(new Comparator<int[]>() {
|
||||||
|
@Override
|
||||||
|
public int compare(int[] nums1, int[] nums2) {
|
||||||
|
return nums1[1] != nums2[1] ? nums2[1] - nums1[1] : nums2[0] - nums1[0];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (int i = 0; i < nums.length; i++) {
|
||||||
|
if (nums[i] == lastNum) {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
if (nums[i] != lastNum) {
|
||||||
|
deque.offer(new int[]{lastNum, count});
|
||||||
|
count = 1;
|
||||||
|
lastNum = nums[i];
|
||||||
|
}
|
||||||
|
//如果是最后一个数了,那就直接放
|
||||||
|
if (i == nums.length - 1) {
|
||||||
|
deque.offer(new int[]{nums[i], count});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int[] result = new int[k];
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
result[i] = deque.poll()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 官方思路:不用先排序,直接用map装<num,count>,装完以后遍历map,用一个小顶堆维护一个大小为k的堆,少于k直接装,大于k就和堆顶元素比
|
||||||
|
* map装复杂度O(n),取map O(1),堆大小只有k,所以堆化操作复杂度O(logk)个,所以最后时间复杂度O(nlogk)
|
||||||
|
* 速度超过94.94%,内存超过25.05%
|
||||||
|
*/
|
||||||
|
public int[] topKFrequent1(int[] nums, int k) {
|
||||||
|
|
||||||
|
HashMap<Integer, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
|
for (int num : nums) {
|
||||||
|
map.put(num, map.getOrDefault(num, 0) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//创建一个小顶堆
|
||||||
|
PriorityQueue<int[]> deque = new PriorityQueue<>(new Comparator<int[]>() {
|
||||||
|
@Override
|
||||||
|
public int compare(int[] nums1, int[] nums2) {
|
||||||
|
return nums1[1] - nums2[1];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
|
||||||
|
Integer num = entry.getKey();
|
||||||
|
Integer count = entry.getValue();
|
||||||
|
|
||||||
|
if(deque.size()<k){
|
||||||
|
deque.offer(new int[]{num,count});
|
||||||
|
}else {
|
||||||
|
if(count>deque.peek()[1]){
|
||||||
|
deque.poll();
|
||||||
|
deque.offer(new int[]{num,count});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] result = new int[k];
|
||||||
|
for (int i = 0; i < k; i++) {
|
||||||
|
result[i]=deque.poll()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue