题目:
一、滑动窗口最大值
第一眼: 暴力遍历,没办法,太菜了
思路:我愿称其为“看潜力法”,在数组nums的值进入滑动窗口时,直接看窗口里前面的值有没有自己大,没自己大就全部创死(pop掉),比自己大就排在他后面,这就像公司里进来一个有潜力的新人,在选新leader的时候就把排在自己前面的比自己潜力小的老人挤掉 :(你卷你@#
原理:因为滑动窗口最大值只选一个,而在每一个值进入时进行竞争,能保证窗口里只有一个值就是最大值,然后选择他,而队列很适合干这个
代码
//自定义数组
class MyQueue{
Deque<Integer> deque = new LinkedList<>();
void poll(int val){
if(!deque.isEmpty() && val == deque.peek()){
deque.poll();
}
}
void add(int val){
while(!deque.isEmpty() && val > deque.getLast()){
deque.removeLast();
}
deque.add(val);
}
int peek(){
return deque.peek();
}
}
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if(nums.length == 1){
return nums;
}
MyQueue myQueue = new MyQueue();
int len = nums.length - k + 1;
int[] res = new int[len];
int num = 0;
//先装k个
for(int i = 0; i < k; i++){
myQueue.add(nums[i]);
}
res[num++] = myQueue.peek();
for(int i = k; i < nums.length; i++){
myQueue.poll(nums[i - k]);
myQueue.add(nums[i]);
res[num++] = myQueue.peek();
}
return res;
}
}
二、前k个高频词
第一眼:用容器装入每个值和其个数,然后对其排序
思路:如果用快排,那么复杂度也要nlogn,但是这道题目不一般,他只取前k个,这意味着我们可以不用对全体排序! 所以我们只需要一个数据结构能够在装入数据的时候进行判断
所以大小堆,可以解决
这道题用小堆更好,因为所以我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。
代码:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer,Integer> map = new HashMap<>();
for(int num : nums){
map.put(num,map.getOrDefault(num,0) + 1);
}
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1,pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
if(pq.size() < k){
pq.add(new int[]{entry.getKey(),entry.getValue()});
} else {
if(entry.getValue() > pq.peek()[1]){
pq.poll();
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] result = new int[k];
for(int i = k - 1; i >= 0; i--)
result[i] = pq.poll()[0];
return result;
}
}