date: 2018-11-25 08:31:30

updated: 2018-11-25 08:31:30

栈&队列&并查集&哈希表(julyedu网课整理)

栈和队列

1.定义

  • 存放数据的线性表
  • 操作:入栈/队列、出栈/队列、判断满/空
  • 空间复杂度:O(n)
  • 单次操作时间复杂度:O(1)
  • 区别
    • 先进后出(FILO, First In Last Out)
    • 先进先出(FIFO, First In First Out)

2.实现

  • 数组和链表皆可(线性表)
  • 指针(辅助变量)
    • 栈顶/底指针
    • 队头/尾指针
  • 关键:出入元素的同时移动指针
    • 队列的头/尾指针都要改变
    • 栈只有栈顶指针改变,栈底指针不变

3.栈的应用:括号匹配检测

  • 括号、引号等符号是成对出现的,必须相互匹配
  • 设计一个算法,自动检测输入的字符串中的括号是否匹配
  • 比如:
  • {}[([][])]     匹配
  • [(])           不匹配
  • (()]           不匹配

思路:

从左到右扫描字符串,当入栈一个 '[' 时就期待一个 ']' ,当且仅当入栈一个 '[' 后紧跟着一个 '] '时, '[' 出栈。

leetcode #394

4.栈的应用:模拟系统栈

int F(int n) {
if (n <= 1)
return 1;
return n * F(n – 1);
}
递归,时间空间复杂度O(n)

生产上应谨慎使用递归,多个项目运行时可能造成栈溢出

原因:每一次递归都要记录上一次的地址,以及下一次的结果,不断递归下去,就会不断增加栈的压力

模拟系统栈:

do {
if (!back) { // back是边界判断
if (n <= 1) {
back = true;
ret = 1;
continue;
}
n进栈;
--n;
}else{
ret *= 出栈;

} while (栈不为空);

并查集

1.定义

  • 存放数据的集合关系,如{1,2}{3,4}{5}
  • 支持操作
    • 建立新集合
    • 查找某个元素属于哪个集合
    • 合并两个集合
  • 均摊时间复杂度近似O(1)

2.应用

  • 假设n个节点,初始时点与点之间没有连接
  • 给出一系列的连接操作
  • 一次连接操作不产生环,则接受,否则被抛弃

哈希表(散列表)

1.定义

  • 根据关键码值(Key,Value)而直接进行访问的数据结构
  • 操作:根据(Key, Value)进行
    • 插入,查找,删除(可以没有)
  • 空间复杂度:O(n)
  • 单次操作时间复杂度:O(1)
  • 本质:Key的索引

2.实现

就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里。

而当使用哈希表进行查询的时候,就是再次使用哈希函数将key转换为对应的数组下标,并定位到该空间获取value,如此一来,就可以充分利用到数组的定位性能进行数据定位

3.例题:Top K

搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。

假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

一共分为两个步骤,第一个是需要先统计出每个Query的次数,第二个是根据统计结果,找出Top K

3.1 统计
3.1.1 归并排序

归并排序和快速排序的期望时间复杂度O(nlogn)

遍历的时间复杂度O(n)

∴总体的时间复杂度是O(n)+O(nlogn) = O(nlogn)

3.1.2 HashTable

HashTable的查询速度非常的快,几乎是O(1)的时间复杂度。

维护一个Key为Query字串,Value为该Query出现次数的HashTable,每次读取一个Query,如果该字串不在Table中,那么加入该字串,并且将Value值设为1;如果该字串在Table中,那么将该字串的计数加一即可。

最终我们在O(N)的时间复杂度内完成了对该海量数据的处理。

3.2 找出Top K
3.2.1 直接排序

三百万数据,每条记录是255Byte,大约0.712G,所以1G内存可以存下

3.2.2 部分排序

题目要求是求出Top 10,因此我们没有必要对所有的Query都进行排序,我们只需要维护一个10个大小的数组,初始化放入10个Query,按照每个Query的统计次数由大到小排序,然后遍历这300万条记录,每读一条记录就和数组最后一个Query对比,如果小于这个Query,那么继续遍历,否则,将数组中最后一条数据淘汰,加入当前的Query。最后当所有的数据都遍历完毕之后,那么这个数组中的10个Query便是我们要找的Top10了。

不难分析出,这样,算法的最坏时间复杂度是O(N*K), 其中K是指top多少。

####### 3.2.3 最小堆

求最大的K个数--最小堆--堆顶放的是K个数里最小的那一个

求最小的K个数--最大堆--堆顶放的是K个数里最大的那一个

具体过程是,堆顶存放的是整个堆中最小的数,现在遍历N个数,把最先遍历到的k个数存放到最小堆中,并假设它们就是我们要找的最大的k个数,X1>X2...Xmin(堆顶),而后遍历后续的N-K个数,一一与堆顶元素进行比较,如果遍历到的Xi大于堆顶元素Xmin,则把Xi放入堆中,而后更新整个堆,更新的时间复杂度为logK,如果Xi<Xmin,则不更新堆,整个过程的复杂度为O(K) + O((N-K)*logK)=O(N * logK)

总结:

第一步用HashTable统计每个Query出现的次数,时间复杂度为O(n);

第二步用采用最小堆找出Top K,时间复杂度O(N*logK)

最终时间复杂度为O(N) + O(N' * logK),N为一千万,N'为三百万

栈&队列&并查集&哈希表(julyedu网课整理)的更多相关文章

  1. LOJ2014 SCOI2016 萌萌哒 并查集、ST表优化连边

    传送门 一个朴素的做法就是暴力连边并查集,可是这是\(O(n^2)\)的.发现每一次连边可以看成两个区间覆盖,这两个区间之间一一对应地连边.可线段树对应的两个节点的size可能不同,这会导致" ...

  2. 5.29 省选模拟赛 波波老师 SAM 线段树 单调队列 并查集

    LINK:波波老师 LINK:同bzoj 1396 识别子串 不过前者要求线性做法 后者可以log过.实际上前者也被我一个log给水过了. 其实不算很水 我自认跑的很快罢了. 都是求经过一个位置的最短 ...

  3. ZOJ:2833 Friendship(并查集+哈希)

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2833 A friend is like a flower, a rose ...

  4. NOIp 数据结构专题总结 (1):STL、堆、并查集、ST表、Hash表

    系列索引: NOIp 数据结构专题总结 (1) NOIp 数据结构专题总结 (2) STL structure STL 在 OI 中的运用:https://oi.men.ci/stl-in-oi/ s ...

  5. 2018.10.01 bzoj3237: [Ahoi2013]连通图(cdq分治+并查集)

    传送门 cdq分治好题. 对于一条边,如果加上它刚好连通的话,那么删掉它会有两个大集合A,B.于是我们先将B中禁用的边连上,把A中禁用的边禁用,再递归处理A:然后把A中禁用的边连上,把B中禁用的边禁用 ...

  6. C#部分---特殊集合:stack栈集合、queue队列集合、哈希表集合。

    1.stack栈集合:又名 干草堆集合 栈集合 特点:(1)一个一个赋值 一个一个取值(2)先进后出实例化 初始化 Stack st = new Stack(); //添加元素用push st.Pus ...

  7. 算法初级面试题05——哈希函数/表、生成多个哈希函数、哈希扩容、利用哈希分流找出大文件的重复内容、设计RandomPool结构、布隆过滤器、一致性哈希、并查集、岛问题

    今天主要讨论:哈希函数.哈希表.布隆过滤器.一致性哈希.并查集的介绍和应用. 题目一 认识哈希函数和哈希表 1.输入无限大 2.输出有限的S集合 3.输入什么就输出什么 4.会发生哈希碰撞 5.会均匀 ...

  8. 2017年11月4日 vs类和结构的区别&哈希表&队列集合&栈集合&函数

    类和结构的区别 类: 类是引用类型在堆上分配,类的实例进行赋值只是复制了引用,都指向同一段实际对象分配的内存 类有构造和析构函数 类可以继承和被继承 结构: 结构是值类型在栈上分配(虽然栈的访问速度比 ...

  9. C#集合类:动态数组、队列、栈、哈希表、字典(转)

    1.动态数组:ArrayList 主要方法:Add.AddRange.RemoveAt.Remove 2.队列:Queue 主要方法:Enqueue入队列.Dequeue出队列.Peek返回Queue ...

随机推荐

  1. ip子网掩码计算及子网划分

    为什么要懂 子网掩码计算,及子网划分属于网络基础知识.一般在几个地方会用到: 公司避免产生网络风暴而划分子网,帮助路由器判断对应主机是否在同一个网段中 服务器相互隔离而划分子网,一般机房管理人员规划: ...

  2. Depthwise Separable Convolution(深度可分离卷积)的实现方式

    按照普通卷积-深度卷积-深度可分离卷积的思路总结. depthwise_conv2d来源于深度可分离卷积,如下论文: Xception: Deep Learning with Depthwise Se ...

  3. Salesforce LWC学习(二十六) 简单知识总结篇三

    首先本篇感谢长源edward老哥的大力帮助. 背景:我们在前端开发的时候,经常会用到输入框,并且对这个输入框设置 required或者其他的验证,当不满足条件时使用自定义的UI或者使用标准的 inpu ...

  4. 动态生成简约MVC请求接口|抛弃一切注解减少重复劳动吧

    背景 目前创建一个后端请求接口给别人提供服务,无论是使用SpringMVC方式注解,还是使用SpringCloud的Feign注解,都是需要填写好@RequestMap.@Controller.@Pa ...

  5. mongodb安装教程(亲测有效)

    网上太多教程了,都是说的不明不白,所以自己整理一份 #参考官网: https://docs.mongodb.com/manual/tutorial/install-mongodb-on-red-hat ...

  6. 微服务实战系列(十)-网关高可用之中间件Keepalived

    1.场景描述 因为要做网关的高可用,用到了keepalived+nginx,来保证nginx的高可用,如下图: 安装了keepavlived,走了一些弯路,记录下吧,nginx的安装就不多说了,博客已 ...

  7. Python-装饰器(语法糖)上下五千年和前世今生

    装饰器上下五千年和前世今生,这里我们始终要问,装饰器为何产生?装饰器产生解决了什么问题?什么样的需求推动了装饰器的产生?思考问题的时候,始终要问,为什么要这样,而不是那样或者其他样.这里我不先说,也不 ...

  8. Centos-配置网络或显示当前网络接口状态-ifconfig

    ifconfig 配置网络或显示当前网络接口状态,必须由root用户执行 相关选项 -a 显示所有网络接口信息,包括活动或非活动 -s 显示活动接口简要信息 -v 如果网卡接口出现错误则返回错误信息 ...

  9. SpringBoot2.3中@Async实现异步

    启动加上@EnableAsync ,需要执行异步方法上加入@Async. 在方法上加上@Async之后 底层使用多线程技术. 不使用异步 先关代码: package com.yiyang.myfirs ...

  10. LVM的简单使用及常用的命令总结

    Lvm的简单使用及常用的命令总结 centos7中默认使用的是xfs文件系统,此文件系统的特点,可以另外查找资料,这里说一下对文件系统的扩容: 1.先看一下没扩容之前的分区大小 2.添加一块新磁盘,并 ...