题目都是第一次做,后面还需巩固!!!
239.滑动窗口最大值
文章链接:代码随想录 (programmercarl.com)
思路:无思路
看完文章的思路:
(a)设计单调队列的时候,pop,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到(说明要用while)push元素的数值小于等于队列入口元素的数值为止
(b)保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
故事:要自己构造单调队列,看到了力扣上讨论@虫子的世界,讲了一个单调队列的故事,非常形象。单调队列真是一种让人感到五味杂陈的数据结构,它的维护过程更是如此.....就拿此题来说,队头最大,往队尾方向单调......有机会站在队头的老大永远心狠手辣,当它从队尾杀进去的时候,如果它发现这里面没一个够自己打的,它会毫无人性地屠城,把原先队里的人头全部丢出去,转身建立起自己的政权,野心勃勃地准备开创一个新的王朝.....这时候,它的人格竟发生了一百八十度大反转,它变成了一位胸怀宽广的慈父!它热情地请那些新来的“小个子”们入住自己的王国......然而,这些小个子似乎天性都是一样的——嫉妒心强,倘若见到比自己还小的居然更早入住王国,它们会心狠手辣地找一个夜晚把它们通通干掉,好让自己享受更大的“蛋糕”;当然,遇到比自己强大的,它们也没辙,乖乖夹起尾巴做人。像这样的暗杀事件每天都在上演,虽然王国里日益笼罩上白色恐怖,但是好在没有后来者强大到足以干翻国王,江山还算能稳住。直到有一天,闯进来了一位真正厉害的角色,就像当年打江山的国王一样,手段狠辣,野心膨胀,于是又是大屠城......历史总是轮回的。
Java代码:
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//判断特殊情况
if(nums.length == 1){
return nums;
}
MyQueue myque = new MyQueue();
//返回数组的长度
int len = nums.length - k + 1;
int[] res = new int[len];
int num = 0;
//先把数组中一开始的k个数加入到队列中
for(int i = 0; i < k;i++){
//按照单调递减的顺序排号
myque.add(nums[i]);
}
//此时队列的顶部为最大值
res[num++] = myque.peek();
//开始移动滑动窗口,移动前要先把最前面的数弹出,然后把当前的数加入到队列中,再记录当前的最大值
for(int i = k ; i <nums.length;i++){
myque.poll(nums[i - k]);
myque.add(nums[i]);
res[num++] = myque.peek();
}
return res;
}
}
//要自定义一个单调队列(单调递减)
class MyQueue{
//用Deque双向队列
Deque<Integer> deque = new LinkedList<>();
//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
//队列长这样,peek()的值为出口的值
/*
出口 入口
-----------------
3 2 1
-----------------
*/
//同时判断队列当前是否为空
void poll(int val){
if(!deque.isEmpty() && val == deque.peek()){
deque.poll();
}
}
//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
//保证队列元素单调递减
//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
void add(int val){
while(!deque.isEmpty() && val > deque.getLast()){
deque.removeLast();
}
deque.offer(val);
}
//队列顶部的元素始终为最大值
int peek(){
return deque.peek();
}
}
学习到的一些语法:
(1)Deque接口的getLast ()方法返回Deque的最后一个元素或尾部。它不会删除元素。当双端队列为空时,它将引发异常。
(2)Java Deque 接口的 removeLast() 方法用于检索和删除给定双端队列的最后一个元素。上述方法与 pollLast() 方法不同,如果给定的双端队列为空,则抛出异常。
347.前K个高频元素
文章链接:代码随想录 (programmercarl.com)
思路:无思路
看完文章后的思路:
(1)先用Map来保存元素值和元素出现的频次
(2)使用PriorityQueue来实现小顶堆,其中Comparator接口正负表示排列顺序
返回负数,形参中第一个参数排在前面;返回正数,形参中第二个参数排在前面
* 对于队列:排在前面意味着往队头靠
* 对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),
* 从队头到队尾按从大到小排就是最大堆(大顶堆)--->队头元素相当于堆的根节点
(3)按照小顶堆,将key,value按照value频次的大小压入到小顶堆中,如果此时堆中个数大于k了,说明前k个频次高的元素已经在里面了,此时可以弹出
Java代码:第一次做先了解思路
算法小白还需继续努力!!!