![](https://img-blog.csdnimg.cn/20201014180756754.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
算法
文章平均质量分 72
lanyubaby
这个作者很懒,什么都没留下…
展开
-
用拉链法实现哈希表
哈希表核心原理 已经介绍过哈希函数和 key 的类型的关系,其中 hash 函数的作用是在 O(1) 的时间把 key 转化成数组的索引,而 key 可以是任意不可变的类型。但是这里为了方便诸位理解,我先做如下简化:1、我们实现的哈希表只支持 key 类型为 int,value 类型为 int 的情况,如果 key 不存在,就返回 -1。2、我们实现的 hash 函数就是简单地取模,即 hash(key) = key % table.length。原创 2024-06-05 00:04:39 · 288 阅读 · 0 评论 -
哈希表基本原理
上面的说明应该已经吧哈希表的底层原理全部串起来了,最后模拟几个面试问题来总结一下本文的内容:1、为什么我们常说,哈希表的增删查改效率都是 O(1)?因为哈希表底层就是操作一个数组,其主要的时间复杂度来自于哈希函数计算索引和哈希冲突。只要保证哈希函数的复杂度在 O(1),且合理解决哈希冲突的问题,那么增删查改的复杂度就都是 O(1)。2、哈希表的遍历顺序为什么会变化?原创 2024-06-05 00:02:22 · 792 阅读 · 0 评论 -
双端队列(Deque)原理及实现
如果你理解了前面讲解的内容,这个双端队列其实没啥可讲的了。标准队列 只能在队尾插入元素,队头删除元素,而双端队列的队头和队尾都可以插入或删除元素。普通队列就好比排队买票,先来的先买,后来的后买;而双端队列就好比一个过街天桥,两端都可以随意进出。当然,双端队列的元素就不再满足「先进先出」了,因为它比较灵活嘛。在做算法题的场景中,双端队列用的不算很多。感觉只有 Python 用到的多一些,因为 Python 标准库没有提供内置的栈和队列,一般会用双端队列来模拟标准队列。原创 2024-06-04 23:54:18 · 304 阅读 · 0 评论 -
用数组实现队列-栈
先用数组实现栈,这个不难,你把动态数组的尾部作为栈顶,然后调用动态数组的 API 就行了。因为数组尾部增删元素的时间复杂度都是 O(1),符合栈的要求。原创 2024-06-04 23:52:35 · 117 阅读 · 0 评论 -
环形数组技巧
数组可能是环形的么?不可能。数组就是一块线性连续的内存空间,怎么可能有环的概念?这段代码的关键在于求模运算 %,也就是求余数。当 i 到达数组末尾元素时,i + 1 和 arr.length 取余数又会变成 0,即会回到数组头部,这样就在逻辑上形成了一个环形数组,永远遍历不完。这就是环形数组技巧。这个技巧如何帮助我们在 O(1) 的时间在数组头部增删元素呢?即,我们仅仅把元素 1 的位置标记为空,但并不做数据搬移。你可以看到,当头部没有位置添加新元素时,它转了一圈,把新元素加到尾部了。原创 2024-06-04 23:51:15 · 556 阅读 · 0 评论 -
用链表实现队列-栈
一些读者应该已经知道该怎么用链表作为底层数据结构实现队列和栈了。因为实在是太简单了,直接调用双链表的 API 就可以了。注意我这里是直接用的 Java 标准库的 LinkedList,如果你用之前我们实现的 MyLinkedList,也是一样的。原创 2024-06-04 23:48:16 · 171 阅读 · 0 评论 -
队列-栈基本原理
栈就像一摞盘子,最先放的压在最下面,最后放的留在最上面,拿的时候也是最上面的先被拿走。所以我们常说,队列是一种「先进先出」的数据结构,栈是一种「先进后出」的数据结构,就是这个道理。说它操作受限,主要是和基本的数组和链表相比,它们提供的 API 是不完整的。比方说我们前面实现的数组和链表,增删查改的 API 都实现过了,你可以对任意一个索引元素进行增删查改,只要索引不越界,就随便你。当然,这个图中把栈竖着画,队列横着画,只是为了更形象,但实际上它们底层都是数组和链表实现的,后面会讲到。原创 2024-06-04 23:45:58 · 238 阅读 · 0 评论 -
动态数组代码实现
下面我会直接给出一个简单的动态数组代码实现,包含了基本的增删查改功能。这里先给出几个关键点,等会你看代码的时候可以着重注意一下。原创 2024-06-03 00:00:30 · 589 阅读 · 2 评论 -
数组(顺序存储)基本原理
我梳理一下上面的因果逻辑,静态数组本质上就是一块连续的内存空间,int arr[10] 这个语句我们可以得知:1、我们知道这块内存空间的首地址(数组名 arr 就指向这块内存空间的首地址)。2、我们知道了每个元素的类型(比如 int),也就是知道了每个元素占用的内存空间大小(比如一个 int 占 4 字节,32 bit)。3、这块内存空间是连续的,其大小为 10 * sizeof(int) 即 40 字节。原创 2024-06-02 23:56:43 · 881 阅读 · 0 评论 -
链表代码实现
下面我会分别用双链表和单链给出一个简单的 MyLinkedList 代码实现,包含了基本的增删查改功能。这里给出几个关键点,等会你看代码的时候可以着重注意一下。原创 2024-06-02 23:49:08 · 698 阅读 · 0 评论 -
链表(链式存储)基本原理
这仅仅是一个最简单的单链表节点,方便力扣出算法题来考你。主要区别有两个:1、编程语言标准库一般都会提供泛型,即你可以指定 val 字段为任意类型,而力扣的单链表节点的 val 字段只有 int 类型。2、编程语言标准库一般使用的都是双链表而非单链表。单链表节点只有一个 next 指针,指向下一个节点;而双链表节点有两个指针,prev 指向前一个节点,next 指向下一个节点。有了 prev 前驱指针,链表支持双向遍历,但由于要多维护一个指针,增删查改时会稍微复杂一些,后面带大家实现双链表时会具体介绍。原创 2024-06-02 23:18:25 · 702 阅读 · 0 评论