LeeCode 239: 滑动窗口最大值

题目描述

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值

建立模型

  1. 单调队列:保存还未被删除的下标, 下标对应的值单调递减
  2. 对于前 k 个数,下标\(0 \le i < j < k\),若 \(nums[i] \ge nums[j]\),则 nums[i]永远不会成为最大值,无需保存
  3. 对于 [k, nums.length() - 1],循环比较队尾元素和当前元素的大小关系,若当前元素大于等于队尾元素则说明队尾元素永远不会成为最大值,无需保存;
  4. 然后插入当前元素下标

代码实现

# Python3 实现
def MaxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
# 特殊情况
if k >= len(nums):
return max(nums) # 使用双端队列保存下标
queue = collections.deque() # 前 k 个元素
for i in range(k):
while queue and nums[queue[-1]] <= nums[i]:
queue.pop()
queue.append(i) res = [nums[queue[0]]]
for i in range(k, len(nums)):
while queue and nums[queue[-1]] <= nums[i]:
queue.pop()
queue.append(i) while queue[0] <= i - k:
queue.popleft()
res.append(nums[queue[0]])
return res
// Java 实现
public int[] maxSlidingWindow(int[] nums, int k) {
if (k >= nums.length) {
// return max(nums);
} Deque<Integer> deque = new ArrayDeque<>(); for (int i = 0; i < k; i++) {
while(!deque.isEmpty() && nums[deque.getLast()] <= nums[i]) {
deque.removeLast();
}
deque.add(i);
} int[] res = new int[nums.length - k + 1];
res[0] = nums[deque.getFirst()];
int index = 1; for (int i = k; i < nums.length; i++) {
while(!deque.isEmpty() && nums[deque.getLast()] <= nums[i]) {
deque.removeLast();
}
deque.add(i);
while (deque.getFirst() <= i - k) {
deque.removeFirst();
} res[index++] = nums[deque.getFirst()];
} return res;
}

LeeCode 347: 前 K 个高频元素

题目描述

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按任意顺序返回答案。

建立模型

这是一个堆的问题,这类问题还有比如前K个高频单词最小K个数等。

  1. 遍历数组统计所有出现的数字和频数
  2. 建立一个存储K个元素的小顶堆(自定义排序规则),每次比较堆顶元素和当前元素
  3. 若当前元素频数大于堆顶元素,则将堆顶元素弹出,添加当前元素
  4. 返回堆中的所有元素

代码实现

// Java 实现
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);
} /**
* 自定义排序规则
* 按照数组第2个元素值从小到大排序
*/
Comparator<int[]> comparator = new Comparator<int[]>() { @Override
public int compare(int[] o1, int[] o2) {
// TODO Auto-generated method stub
return o1[1] - o2[1];
} };
// 小顶堆的实现
PriorityQueue<int[]> queue = new PriorityQueue<>(comparator); for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
int num = entry.getKey();
int value = entry.getValue(); if (queue.size() < k) {
queue.offer(new int[]{num, value});
}
else {
if (queue.peek()[1] < value) {
queue.poll();
queue.offer(new int[]{num, value});
}
}
} int[] res = new int[k];
int index = 0;
while (index < k) {
res[index++] = queue.poll()[0];
} return res;
}
  • Python3待更新,需手动实现堆

LeeCode 栈与队列问题(二)的更多相关文章

  1. 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

    数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...

  2. 剑指offer-第二章数据结构(数组,字符串,链表,树,栈与队列)及例题

    一.数组(最简单的数据结构) 定义:占据一块连续内存并按照顺序存储数据.创建时先指定大小,分配内存. 优点:时间效率高.实现简单的hash(下标为key,对应的数据为value) 缺点:空间效率差.如 ...

  3. leecode刷题(26)-- 用栈实现队列

    leecode刷题(26)-- 用栈实现队列 用栈实现队列 使用栈实现队列的下列操作: push(x) -- 将一个元素放入队列的尾部. pop() -- 从队列首部移除元素. peek() -- 返 ...

  4. SDUT-2132_数据结构实验之栈与队列二:一般算术表达式转换成后缀式

    数据结构实验之栈与队列二:一般算术表达式转换成后缀式 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 对于一个基于二元运 ...

  5. 二、 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek)

    请指教交流! package com.it.hxs.c01; import java.util.Stack; /* 编写一个类,用两个栈实现队列,支持队列的基本操作(add,poll,peek) */ ...

  6. 剑指Offer面试题:6.用两个栈实现队列

    一.题目:用两个栈实现队列 题目:用两个栈实现一个队列.队列的声明如下,请实现它的两个函数appendTail和deleteHead,分别完成在队列尾部插入结点和在队列头部删除结点的功能. 原文是使用 ...

  7. C实现栈和队列

    这两天再学习了数据结构的栈和队列,思想很简单,可能是学习PHP那会没有直接使用栈和队列,写的太少,所以用具体代码实现的时候出现了各种错误,感觉还是C语言功底不行.栈和队列不论在面试中还是笔试中都很重要 ...

  8. JavaScript中的算法之美——栈、队列、表

    序 最近花了比较多的时间来学习前端的知识,在这个期间也看到了很多的优秀的文章,其中Aaron可能在这个算法方面算是我的启蒙,在此衷心感谢Aaron的付出和奉献,同时自己也会坚定的走前人这种无私奉献的分 ...

  9. Java数据结构和算法之栈与队列

    二.栈与队列 1.栈的定义 栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表. (1)通常称插入.删除的这一端为栈顶(Top),另一端称为栈底(Bottom). (2)当表中没有元素时称为 ...

  10. 栈和队列的面试题Java实现【重要】

    栈和队列: 面试的时候,栈和队列经常会成对出现来考察.本文包含栈和队列的如下考试内容: (1)栈的创建 (2)队列的创建 (3)两个栈实现一个队列 (4)两个队列实现一个栈 (5)设计含最小函数min ...

随机推荐

  1. C# POST GET请求方式汇总

    /// <summary> /// POST方式提交 application/json /// </summary> /// <param name="post ...

  2. 当MYSQL报错时

    输入mysqld  --console查看错误 针对error行进行排查

  3. Linux让部署在服务器上的项目一直保持运行状态…&跑多个项目

    在idea通过package得到的.jar包或者.war包可通过 java -jar xxx.jar/xxx.war 命令直接在linux或者windows系统运行:   将打好包的项目放在linux ...

  4. Expression #1 of SELECT list is not in GROUP BY clause and contains nonag

    报错信息: Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'a.rs ...

  5. linux安装mongo-c-driver

    yum install mongo-c-driver sudo yum install cmake openssl-devel cyrus-sasl-devel $ wget https://gith ...

  6. Rstudio R get filename full path

    FILENAME=basename(rstudioapi::getActiveDocumentContext()$path) FULLPATH=dirname(rstudioapi::getActiv ...

  7. C语言声明与定义的区别

    转自:https://blog.csdn.net/gatieme/article/details/50640424 C++程序通常由许多文件组成,为了让多个文件访问相同的变量,C++区分了声明和定义. ...

  8. Linux查看CPU 内存命令

    查看CPU 内存命令:https://www.cnblogs.com/ggjucheng/archive/2013/01/14/2859613.html 查看某一进程内存占用:ps -ef 获取PID ...

  9. 转帖:巧用Stream优化老代码,太清爽了!

    Java8的新特性主要是Lambda表达式和流,当流和Lambda表达式结合起来一起使用时,因为流申明式处理数据集合的特点,可以让代码变得简洁易读 放大招,流如何简化代码 如果有一个需求,需要对数据库 ...

  10. day2Java程序基础

    Java程序基础 Java程序基本结构 一个程序的基本单位是class,class是关键字 类名要求: 类名必须以英文字母开头,后接字母,数字和下划线的组合 习惯以大写字母开头 public除了修饰类 ...