算法训练营(第一期)第十一天(java)
学习感悟:
题目
一、滑动窗口的最大值(leetcode239)
错误解法:使用二层循环但是出现超出时间限制
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
int[] result=new int[nums.length-k+1];
//我想最简单的方法应该就是两层for循环
for(int i=0;i<nums.length;i++){
if(nums.length-i<k) break;
int max=nums[i];
for(int j=i;j<i+k;j++){
if(nums[j]>max){
max=nums[j];
}else{
max=max;
}
}
result[i]=max;
}
return result;
}
}
正确解法:使用栈来解决问题
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
//我们可以自定义一套规则来维护一个单调递减的队列保证了每次弹出的元素都是要被滑动走的元素
Deque<Integer> q=new LinkedList<>();
int[] result=new int[nums.length-k+1];
for(int i=0;i<k;i++){
push(q,nums[i]);
}
int count=0;
result[count++]=getMaxValue(q);
for(int i=k;i<nums.length;i++){
poll(q,nums[i-k]);
push(q,nums[i]);
result[count++]=getMaxValue(q);
}
return result;
}
void poll(Deque q,int x){
//弹出元素,弹出的前提是队头的元素要是数组中要移除的元素
if(!q.isEmpty()&& x==(int)q.peek()){
q.poll();
}
}
int getMaxValue(Deque q){
return (int)q.peek();
}
void push(Deque q,int x){
//送入后保证前面比其小的元素都被移除
while(!q.isEmpty()&&x > (int)q.getLast()){
q.removeLast();
}
q.add(x);
}
}
二、前 K 个高频元素(leetcode347)
题目
代码明天补充
解法:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
//采用栈与队列的方法来解决,怎么解决?
//采用暴力方法,hash方法,但是我还要对value排序这可如何是好?
HashMap<Integer,Integer> hm=new HashMap();
for(int i=0;i<nums.length;i++){
hm.put(nums[i],hm.getOrDefault(nums[i],0)+1);
}
//使用小顶堆对hashmap进行排序
PriorityQueue<int[]> pq=new PriorityQueue(new Comparator<int[]>(){
public int compare(int[] temp1,int[] temp2){
if(temp1[1]-temp2[1]>=0) return 1;
else return -1;
}
});
//往里面放value如果大于k而且要添加的元素的value也要大于开头则将头部弹出,但是我怎么知道那个value对应那个key呢?那我就对键值对进行排序
for(Map.Entry<Integer,Integer> entry:hm.entrySet()){
if(pq.size()<k){
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
//
if(pq.peek()[1]<entry.getValue()){
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;
}
}