数据结构与算法

2023-05-16

为什么要学习数据结构与算法

1.数据结构+算法=程序
2.代码化繁为简
3.提高代码性能
4.提高面试通过率

栈的概念
  1. 栈是一种遵从后进先出原则的有序集合
  2. 添加新元素的一端称为栈顶,另一端称为栈底
  3. 操作栈的元素时,只能从栈顶操作(添加、移除或取值)
栈的实现
  1. push()入栈方法
  2. pop()出栈方法
  3. top()获取栈顶值
  4. size()获取栈的元素个数
  5. clear()清空栈
class Stack {
  constructor () {
    // 存储栈的数据
    this.data = {}
    // 记录栈的数据个数(相当于数组的 length)
    this.count = 0
  }
  // push() 入栈方法
  push (item) {
    // 方式1:数组方法 push 添加
    // this.data.push(item)
    // 方式2:利用数组长度
    // this.data[this.data.length] = item
    // 方式3:计数方式
    this.data[this.count] = item
    // 入栈后,count 自增
    this.count++
  }
  // pop() 出栈方法
  pop () {
    // 出栈的前提是栈中存在元素,应先行检测
    if (this.isEmpty()) {
      console.log('栈为空!')
      return
    }
    // 移除栈顶数据
    // 方式1:数组方法 pop 移除
    // return this.data.pop()
    // 方式2:计数方式
    const temp = this.data[this.count - 1]
    delete this.data[--this.count]
    return temp
  }
  // isEmpty() 检测栈是否为空
  isEmpty () {
    return this.count === 0
  }
  // top() 用于获取栈顶值
  top () {
    if (this.isEmpty()) {
      console.log('栈为空!')
      return
    }
    return this.data[this.count - 1]
  }
  // size() 获取元素个数
  size () {
    return this.count
  }
  // clear() 清空栈
  clear () {
    this.data = []
    this.count = 0
  }
}


const s = new Stack()
s.push('a')
s.push('b')
s.push('c')

每日温度(LeetCode精选题目)
/**
 * @param {number[]} T 每日温度数组 [73, 74, 75, 71, 69, 72, 76, 73]
 * @return {number[]} 等待天数列表 [1, 1, 4, 2, 1, 1, 0, 0]
 */
var dailyTemperatures = function(T) {
  // 创建单调栈用于记录(存储索引值,用于记录天数)
  const stack = [0]
  let count = 1

  // 创建结果数组(默认将结果数组使用 0 填充)
  const len = T.length
  const arr = new Array(len).fill(0)

  // 遍历 T
  for (let i = 1; i < len; i++) {
    let temp = T[i]
    // 使用 temp 比较栈顶值,如果栈顶值小,出栈(计算日期差,并存储),并重复操作
    //  - stack[count - 1] 代表栈顶值
    while (count && temp > T[stack[count - 1]]) {
      // 出栈
      let index = stack.pop()
      count--
      // 计算 index 与 i 的差,作为 index 位置的升温日期的天数使用 
      arr[index] = i - index
    }
    // 处理完毕,当前温度入栈(等待找到后续的更大温度)
    stack.push(i)
    count++
  }
  return arr
}

队列

队列的概念
  1. 队列是一种遵从先进先出原则的有序集合
  2. 添加新元素的一端称为队尾,另一端称为队首
队列的实现
  1. enqueue()入队方法
  2. dequeue()出队方法
  3. top()获取队首值
  4. size()获取队列的元素个数
  5. clear()清空队列
class Queue {
  constructor () {
    // 用于存储队列数据
    this.queue = []
    this.count = 0
  }
  // 入队方法
  enQueue (item) {
    this.queue[this.count++] = item
  }
  // 出队方法
  deQueue () {
    if (this.isEmpty()) {
      return
    }
    // 删除 queue 的第一个元素
    // delete this.queue[0]
    // 利用 shift() 移除数组的第一个元素
    this.count--
    return this.queue.shift()
  }
  isEmpty () {
    return this.count === 0
  }
  // 获取队首元素值
  top () {
    if (this.isEmpty()) {
      return
    }
    return this.queue[0]
  }
  size () {
    return this.count
  }
  clear () {
    // this.queue = []
    this.length = 0
    this.count = 0
  }
}

const q = new Queue()
双端队列

双端队列指的是允许同时从队尾和队首两端进行存取操作的队列,操作更加灵活
双端队列与JavaScript中的数组操作十分相似,只是不允许在数组两端以外的位置进行存取操作

双端队列实现
  1. addFront/addBack
  2. removeFront/removeBack
  3. frontTop/backTop
class Deque {
  constructor () {
    this.queue = {}
    this.count = 0
    this.head = 0
  }
  // 队首添加
  addFront (item) {
    this.queue[--this.head] = item
  }
  // 队尾添加
  addBack (item) {
    this.queue[this.count++] = item
  }
  // 队首删除
  removeFront () {
    if (this.isEmpty()) {
      return
    }
    const headData = this.queue[this.head]
    delete this.queue[this.head++]
    return headData
  }
  // 队尾删除
  removeBack () {
    if (this.isEmpty()) {
      return
    }
    const backData = this.queue[this.count - 1]
    delete this.queue[--this.count]
    // this.count-- 与 上一步 this.count - 1 合并
    return backData
  }
  // 获取队首值
  frontTop () {
    if (this.isEmpty()) {
      return
    }
    return this.queue[this.head]
  }
  // 获取队尾值
  backTop () {
    if (this.isEmpty()) {
      return
    }
    return this.queue[this.count - 1]
  }
  isEmpty () {
    return this.size() === 0
  }
  size () {
    return this.count - this.head
  }
}

const deq = new Deque()
队列的最大值(LeetCode精选题目)
var MaxQueue = function() {
  // 存储队列数据
  this.queue = {}
  // 双端队列维护最大值(每个阶段的最大值)
  this.deque = {}
  // 准备队列相关的数据
  this.countQ = this.countD = this.headQ = this.headD = 0
};

/** 队尾入队
 * @param {number} value
 * @return {void}
 */
MaxQueue.prototype.push_back = function(value) {
  // 数据在 queue 入队
  this.queue[this.countQ++] = value
  // 检测是否可以将数据添加到双端队列
  //   - 队列不能为空
  //   - value 大于队尾值
  while (!this.isEmptyDeque() && value > this.deque[this.countD - 1]) {
    // 删除当前队尾值
    delete this.deque[--this.countD]
  }
  // 将 value 入队
  this.deque[this.countD++] = value
};

/** 队首出队
 * @return {number}
 */
MaxQueue.prototype.pop_front = function() {
  if (this.isEmptyQueue()) {
    return - 1
  }
  // 比较 deque 与 queue 的队首值,如果相同,deque 出队,否则 deque 不操作
  if (this.queue[this.headQ] === this.deque[this.headD]) {
    delete this.deque[this.headD++]
  }
  // 给 queue 出队,并返回
  const frontData = this.queue[this.headQ]
  delete this.queue[this.headQ++]
  return frontData
};

/** 获取队列最大值
 * @return {number}
 */
MaxQueue.prototype.max_value = function() {
  if (this.isEmptyDeque()) {
    return -1
  }
  // 返回 deque 队首值即可
  return this.deque[this.headD]
};

/** 检测队列 deque 是否为空
 * 
 */
MaxQueue.prototype.isEmptyDeque = function () {
  return !(this.countD - this.headD)
};

/** 检测队列 Queue 是否为空
 * 
 */
MaxQueue.prototype.isEmptyQueue = function () {
  return !(this.countQ - this.headQ)
};
滑动窗口的最大值(LeetCode精选题目)
/**
 * @param {number[]} nums 传入数组
 * @param {number} k 滑动窗口宽度
 * @return {number[]} 
 */
var maxSlidingWindow = function(nums, k) {
  if (k <= 1) {
    return nums
  }
  const result = []
  const deque = []
  // 1 将窗口第一个位置的数据添加到 deque 中,保持递减
  deque.push(nums[0])
  let i = 1
  for (; i < k; i++) {
    // - 存在数据
    // - 当前数据大于队尾值
    //   - 出队,再重复比较
    while (deque.length && nums[i] > deque[deque.length - 1]) {
      deque.pop()
    }
    deque.push(nums[i])
  }
  // 将第一个位置的最大值添加到 result
  result.push(deque[0])

  // 2 遍历后续的数据
  const len = nums.length
  for (; i < len; i++) {
    // 同上进行比较
    while (deque.length && nums[i] > deque[deque.length - 1]) {
      deque.pop()
    }
    deque.push(nums[i])
    // 检测当前最大值是否位于窗口外
    if (deque[0] === nums[i - k]) {
      deque.shift()
    }
    // 添加最大值到 result
    result.push(deque[0])
  }

  return result
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构与算法 的相关文章

  • 以OpenGL/ES视角介绍gfx-hal(Vulkan) Shader/Program接口使用

    文档列表见 Rust 移动端跨平台复杂图形渲染项目开发系列总结 目录 背景 The right way to tackle this in Vulkan is to use resource descriptors A descriptor
  • 数据结构中常见的树(BST二叉搜索树、AVL平衡二叉树、RBT红黑树、B-树、B+树、B*树)

    原文 http blog csdn net sup heaven article details 39313731 数据结构中常见的树 BST二叉搜索树 AVL平衡二叉树 RBT红黑树 B 树 B 树 B 树 转载 2014年09月16日
  • python 历险记(五)— python 中的模块

    目录 前言 基础 模块化程序设计 模块化有哪些好处 什么是 python 中的模块 引入模块有几种方式 模块的查找顺序 模块中包含执行语句的情况 用 dir 函数来窥探模块 python 的内置模块有哪些 结语 参考文档 系列文章列表 前言
  • 将二叉树转为有序的双向链表

    一 题目要求 输入一棵二叉排序树 现在要将该二叉排序树转换成一个有序的双向链表 而且在转换的过程中 不能创建任何新的结点 只能调整树中的结点指针的指向来实现 include
  • 数据结构之链表与线性表

    数据结构之链表与线性表 线性表 顺序线性表 顺序表 顺序线性表 使用数组实现 一组地址连续的存储单元 数组大小有两种方式指定 一是静态分配 二是动态扩展 优点 随机访问特性 查找O 1 时间 存储密度高 逻辑上相邻的元素 物理上也相邻 缺点
  • 一文弄懂循环链表、双向链表、静态链表

    循环链表 双向链表 静态链表 三遍定律 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 理解了单链表本文的理解易如反掌 单链表请点击这里 1 循环链表 将单链表中终端结点的指针端由空指针改
  • 4399 C++笔试题

    1 写出一个函数 取到链表中倒数第二个节点 双链表 node getSec List mylist return mylist m tail gt m prev m prev为链表前指针 单链表 node getSec List mylis
  • (笔试前准备)字符串匹配算法总结

    我想说一句 我日 我讨厌KMP KMP虽然经典 但是理解起来极其复杂 好不容易理解好了 便起码来巨麻烦 老子就是今天图书馆在写了几个小时才勉强写了一个有bug的 效率不高的KMP 特别是计算next数组的部分 其实 比KMP算法速度快的算法
  • 手把手教你实现一个向量

    文章目录 什么是向量 向量提供哪些接口 实现 宏定义 定义类 成员变量 构造函数与析构函数 构造函数 析构函数 成员函数 size get r put r e expand insert r e remove lo hi remove r
  • Python 实现列队

    1 列队定义 队列是项的有序结合 其中添加新项的一端称为队尾 移除项的一端称为队首 当一个元素从队尾进入队列时 一直向队首移动 直到它成为下一个需要移除的元素为止 最近添加的元素必须在队尾等待 集合中存活时间最长的元素在队首 这种排序成为
  • 数据结构——计算节点个数和二叉树高度(C语言版)

    摘自 数据结构 计算节点个数和二叉树高度 C语言版 作者 正弦定理 发布时间 2020 12 12 23 27 09 网址 https blog csdn net chinesekobe article details 111086664
  • 浮生六记

    浮生六记 目录 浮生六记卷一 闺房记乐 002 浮生六记卷二 闲情记趣 015 浮生六记卷三 坎坷记愁 022 浮生六记卷四 浪游记快 034 浮生六记 2 浮生六记卷一 闺房记乐 余生乾隆癸未冬十一月二十有二日 正值太平盛世 且在 衣冠之
  • 人工智能概念

    人工智能概念 人工智能就是用人工方法在机器 计算机 上实现的智能 或称机器智能 即是研究如何用计算机来表示和执行人类的智能活动 以模拟人脑所从事的推理 学习 思考和规划等思维活动 并解决需要人类的智力才能处理的复杂问题 如医疗诊断 管理决策
  • 算法学习——贪心算法之币种统计

    算法描述 币种统计 单位给每一位员工发工资 精确到元 为了保证不临时换零钱 使得每个员工取款的张数最少 在取工资前统计所有员工所需要的各种票面的张数 约定票种为100 50 20 10 5 2 1元 并验证币种统计是否正确 算法思路 算法描
  • Linux 内核中的 Device Mapper 机制

    Linux 内核中的 Device Mapper 机制 尹 洋 在读博士生 尹洋 中科院计算所国家高性能计算机工程技术研究中心的在读博士生 主要从事服务部署和存储资源管理以及Linux块设备一级的开发和研究工作 简介 本文结合具体代码对 L
  • 用两个栈实现队列

    目录 一 栈的基本结构及其接口 二 我的队列结构定义 三 我的队列创建及其初始化 四 我的队列入队 五 我的队列出队 六 我的队列取队头元素 七 我的队列判空 八 我的队列销毁 一 栈的基本结构及其接口 栈的结构定义 typedef int
  • 按照层次遍历结果打印完全二叉树

    按照层次遍历结果打印完全二叉树 按照推论结果 l 层首个节点位置 2 h l 1 l 层节点间距 2 h l 1 1 编码实现 public static
  • 从源码角度来谈谈 HashMap

    HashMap的知识点可以说在面试中经常被问到 是Java中比较常见的一种数据结构 所以这一篇就通过源码来深入理解下HashMap 1 HashMap的底层是如何实现的 基于JDK8 1 1 HashMap的类结构和成员 HashMap继承
  • 浅谈归并排序:合并 K 个升序链表的归并解法

    在面试中遇到了这道题 如何实现多个升序链表的合并 这是 LeetCode 上的一道原题 题目具体如下 用归并实现合并 K 个升序链表 LeetCode 23 合并K个升序链表 给你一个链表数组 每个链表都已经按升序排列 请你将所有链表合并到
  • 排序:计数排序

    一 概念 计数排序是非比较排序 是对哈希直接定址法的变形应用 二 思想 利用数组统计相同数据出现的次数 例如整型数据m出现n次 就在数组m位置记录数据为n 最后从头遍历数组打印数据即可 通俗来讲就是 数组下标即为数据 下标所指位置的值即为数

随机推荐

  • 猿创征文|【电源专题】案例:怎么用万用表测试静态电流IQ

    目录 nbsp nbsp nbsp nbsp 静态电流在生活中的例子 nbsp nbsp nbsp nbsp 什么是静态电流IQ 关断电流 非开关静态电流 lt
  • IDEA找不到Maven插件原因及解决办法

    IDEA找不到Maven插件原因及解决办法 报错如下 xff0c 因为我自己的报错解决了 xff0c 所以借用了别人的图 xff0c 侵删 在idea中你会发现明明在pom xml中加入了插件但依然会报错 xff0c 并且不会下载 解决办法
  • linux系统用户自动登陆不需要输入密码设置

    使用于ubuntu linux unix 一 删除密码 root 64 ubuntu passwd d root 或者 passwd root d 二 修改sshd config文件 root 64 ubuntu cd etc ssh ro
  • 新建springboot项目报错

    未能配置数据源 xff1a url 属性未指定 xff0c 无法配置嵌入式数据源 原因 xff1a 无法确定合适的驱动程序类别 如果您想要一个嵌入式数据库 xff08 H2 HSQL或Derby xff09 xff0c 请将其放在类路径上
  • 伪分布搭建hadoop

    伪分布式搭建hadoop 伪分布模式准备工作以root权限修改ip xff0c 配置关网等修改完IP地址后 xff0c 需要重启网络服务查看ip和是否能ping通修改主机名修改域名映射文件关闭防火墙ssh免密登陆 安装JDK卸载之前的JDK
  • Java实现AI机器人聊天

    文章目录 前言一 账号注册申请密钥二 参数详情三 Java集成1 调用接口2 响应数据 四 效果总结 前言 OpenAI API 几乎可以应用于任何涉及理解或生成自然语言或实现代码等场景 提供一系列具有不同学习训练的模型 xff0c 适用于
  • 使用全局阈值进行灰度图像二值化

    1 原理 选取阈值的一种方法就是图像直方图的视觉检测 选择 T 的另一个方法是反复实验 xff0c 选取不同的阈值 xff0c 直到观测者觉得产生了较好的结果为止 xff0c 这在交互环境下特别有效 例如 xff0c 这种方法允许 使用者通
  • Linux动静态库

    文章目录 Linux动静态库认识动静态库动态库静态库 静态库的打包与使用静态库的打包静态库的使用 动态库的打包与使用动态库的打包动态库的使用 Linux动静态库 认识动静态库 我们先来看一段代码 xff1a span class token
  • GPS启动方式、定位速度、定位精度介绍

    前面文章介绍了GPS定位基础知识 GPS定位知识介绍 qq com 本文主要介绍GPS启动方式 定位过程中最重要的辅助信息是时间 星历 位置 根据辅助信息不同
  • window11上Linux环境搭建

    以下的大部分图片来自网上 xff0c 本人在操作过程中忘记截图记录了 xff0c 但是发出来的这些和我做的是一模一样的 xff01 xff01 一 点击下载centOS7镜像 centos 7 9 2009 isos x86 64安装包下载
  • SQLyog连接MySQL出现错误,提示Client does not support authentication protocol requested by server的解决方法

    问题 xff1a 自己电脑安装了MySQL8 0 26版本 xff0c 但从网上找到破解版的SQLyog软件 xff0c 在装好SQLyog后连接不上 xff0c 会弹出 Client does not support authentica
  • C++的基础知识学习笔记

    C 43 43 的基础知识学习 1 3变量 作用 xff1a 给一段指定的内存空间起名 xff0c 方便操作这段内存 语法 xff1a 数据类型 变量名 61 初始值 xff1b int a 61 1 xff1b 变量存在的意义 xff1a
  • zsh 配置指南

    zsh 配置指南 前言 在Linux系统中 xff0c 我们厂用终端输入命令与系统进行交互 xff0c 大多Linux系统使用的shell为bash 但bash中的功能和色调非常简单和单调 xff0c 往往想达到一个趁手的命令行工具 xff
  • linux/swupd基础命令讲解---基础篇

    一 原生linux ubuntu unix系统安装基础命令 root 64 ubuntu clrtrust generate root 64 ubuntu s wupd bundle add network basic root 64 ub
  • Ros_Canopen:ROS与底盘的can通讯使用

    ROS CANOPEN ROS与底盘的can通讯使用 这篇文章记录了ros canopen的安装和使用过程 xff0c 系统版本为ubuntu16 04 并且已经安装了ROS xff08 kienect 安装过程可能会出现错误 xff0c
  • casbin的详细理解过程(附图片理解)(rbac模型)

    一 casbin模型 casbin模型又叫PERM模型 xff1a subject sub 访问实体 xff0c object xff08 obj访问的资源 xff09 和action xff08 act访问方法 xff09 eft xff
  • EKF(拓展卡尔曼滤波)学习笔记:

    一些参考 xff1a xff08 三十九 xff09 通俗易懂理解 卡尔曼滤波与扩展卡尔曼滤波 知乎 zhihu com 50 封私信 42 条消息 如何通俗并尽可能详细地解释卡尔曼滤波 xff1f 知乎 zhihu com 视觉slam1
  • MSCKF学习笔记

    1 IMU简介 xff1a 测量物体三轴姿态角及加速度的装置 一般IMU包括三轴陀螺仪及三轴加速度计 IMU通常包含陀螺仪 Gyroscope 加速度计 Accelermeters 现代的陀螺仪 MEMS 输出的是旋转变化率 Rotatio
  • 树莓派串口编程c语言

    一 xff1a 初次使用树莓派串口编程 xff0c 需要配置 1 进入 cmdline txt 文档 指令 xff1a cd boot sudo vim cmdline txt 2 删除 之间的部分 dwc otg lpm enable s
  • 数据结构与算法

    为什么要学习数据结构与算法 1 数据结构 43 算法 61 程序 2 代码化繁为简 3 提高代码性能 4 提高面试通过率 栈 栈的概念 栈是一种遵从后进先出原则的有序集合添加新元素的一端称为栈顶 xff0c 另一端称为栈底操作栈的元素时 x