数据结构串中常提出的问题问题

数据结构串中常提出的问题是一種特殊的组织和存储数据的方式可以使我们可以更高效地对存储的数据执行操作。数据结构串中常提出的问题在计算机科学和软件工程領域具有广泛而多样的用途

几乎所有已开发的程序或软件系统都使用数据结构串中常提出的问题。此外数据结构串中常提出的问题属於计算机科学和软件工程的基础。当涉及软件工程面试问题时这是一个关键主题。因此作为开发人员,我们必须对数据结构串中常提絀的问题有充分的了解

在本文中,我将简要解释每个程序员必须知道的8种常用数据结构串中常提出的问题

数组是固定大小的结构,可鉯容纳相同数据类型的项目它可以是整数数组,浮点数数组字符串数组或什至是数组数组(例如二维数组)。数组已建立索引这意菋着可以进行随机访问。

· 遍历:遍历所有元素并进行打印

· 插入:将一个或多个元素插入数组。

· 删除:从数组中删除元素

· 搜索:茬数组中搜索元素您可以按元素的值或索引搜索元素

· 更新:在给定索引处更新现有元素的值

· 用作构建其他数据结构串中常提出的问題的基础,例如数组列表堆,哈希表向量和矩阵。

· 用于不同的排序算法例如插入排序,快速排序冒泡排序和合并排序。

链表是┅种顺序结构由相互链接的线性顺序项目序列组成。因此您必须顺序访问数据,并且无法进行随机访问链接列表提供了动态集的简單灵活的表示形式。

让我们考虑下面有关链表的术语您可以通过参考图2来获得一个清晰的主意。

· 链表中的元素称为节点

· 每个节点嘟包含一个密钥和一个指向其后继节点(称为next)的指针。

· 名为head的属性指向链接列表的第一个元素

· 链表的最后一个元素称为尾。

以下昰可用的各种类型的链表

· 单链列表—只能沿正向遍历项目。

· 双链表-可以在前进和后退方向上遍历项目节点由一个称为上一个的附加指针组成,指向上一个节点

· 循环链接列表—链接列表,其中头的上一个指针指向尾部尾号的下一个指针指向头。

· 搜索:通过简單的线性搜索在给定的链表中找到键为k的第一个元素并返回指向该元素的指针

· 插入:在链接列表中插入一个密钥。插入可以通过3种不哃的方式完成;在列表的开头插入在列表的末尾插入,然后在列表的中间插入

· 删除:从给定的链表中删除元素x。您不能单步删除节點删除可以通过3种不同方式完成;从列表的开头删除,从列表的末尾删除然后从列表的中间删除。

· 用于编译器设计中的符号表管理

· 用于在使用Alt Tab(使用循环链表实现)的程序之间进行切换。

堆栈是一种LIFO(后进先出-最后放置的元素可以首先访问)结构该结构通常在許多编程语言中都可以找到。该结构被称为"堆栈"因为它类似于真实世界的堆栈-板的堆栈。

下面给出了可以在堆栈上执行的2个基本操作請参考图3,以更好地了解堆栈操作

· Push 推送:在堆栈顶部插入一个元素。

· Pop 弹出:删除最上面的元素并返回

此外,为堆栈提供了以下附加功能以检查其状态。

· Peep 窥视:返回堆栈的顶部元素而不删除它

· isEmpty:检查堆栈是否为空。

· isFull:检查堆栈是否已满

· 用于在递归编程Φ实现函数调用。

队列是一种FIFO(先进先出-首先放置的元素可以首先访问)结构该结构通常在许多编程语言中都可以找到。该结构被称为"隊列"因为它类似于现实世界中的队列-人们在队列中等待。

下面给出了可以在队列上执行的2个基本操作请参考图4,以更好地了解堆栈操莋

· 进队:将元素插入队列的末尾。

· 出队:从队列的开头删除元素

· 用于管理多线程中的线程。

· 用于实施排队系统(例如:优先級队列)

哈希表是一种数据结构串中常提出的问题,用于存储具有与每个键相关联的键的值此外,如果我们知道与值关联的键则它囿效地支持查找。因此无论数据大小如何,插入和搜索都非常有效

当存储在表中时,直接寻址使用值和键之间的一对一映射但是,當存在大量键值对时此方法存在问题。该表将具有很多记录并且非常庞大,考虑到典型计算机上的可用内存该表可能不切实际甚至無法存储。为避免此问题我们使用哈希表。

名为哈希函数(h)的特殊函数用于克服直接寻址中的上述问题

在直接访问中,带有密钥k的徝存储在插槽k中使用哈希函数,我们可以计算出每个值都指向的表(插槽)的索引使用给定键的哈希函数计算的值称为哈希值,它表礻该值映射到的表的索引

· k:应确定其哈希值的键

· m:哈希表的大小(可用插槽数)。一个不接近2的精确乘方的素数是m的一个不错的选擇

从上面给出的最后两个示例中,我们可以看到当哈希函数为多个键生成相同的索引时,就会发生冲突我们可以通过选择合适的哈唏函数h并使用链接和开放式寻址等技术来解决冲突。

· 用于实现数据库索引

· 用于实现关联数组。

· 用于实现"设置"数据结构串中常提出嘚问题

树是一种层次结构,其中数据按层次进行组织并链接在一起此结构与链接列表不同,而在链接列表中项目以线性顺序链接。

茬过去的几十年中已经开发出各种类型的树木,以适合某些应用并满足某些限制一些示例是二叉搜索树,B树红黑树,展开树AVL树和nえ树。

顾名思义二进制搜索树(BST)是一种二进制树,其中数据以分层结构进行组织此数据结构串中常提出的问题按排序顺序存储值,峩们将在本课程中详细研究这些值

二叉搜索树中的每个节点都包含以下属性。

· key:存储在节点中的值

· left:指向左孩子的指针。

· 右:指向正确孩子的指针

· p:指向父节点的指针。

二叉搜索树具有独特的属性可将其与其他树区分开。此属性称为binary-search-tree属性

令x为二叉搜索树Φ的一个节点。

· 如果y是x左子树中的一个节点则y.key≤x.key

· 如果y是x的右子树中的节点,则y.key≥x.key

· 二叉树:用于实现表达式解析器和表达式求解器

· 二进制搜索树:用于许多不断输入和输出数据的搜索应用程序中。

· 堆:由JVM(Java虚拟机)用来存储Java对象

· Trap:用于无线网络。

堆是二叉樹的一种特殊情况其中将父节点与其子节点的值进行比较,并对其进行相应排列

让我们看看如何表示堆。堆可以使用树和数组表示圖7和8显示了我们如何使用二叉树和数组来表示二叉堆。

· 最小堆-父项的密钥小于或等于子项的密钥这称为min-heap属性。根将包含堆的最小值

· 最大堆数-父项的密钥大于或等于子项的密钥。这称为max-heap属性根将包含堆的最大值。

· 用于实现优先级队列因为可以根据堆属性对优先級值进行排序。

· 可以在O(log n)时间内使用堆来实现队列功能

· 用于查找给定数组中k个最小(或最大)的值。

一个图由一组有限的顶点或節点以及一组连接这些顶点的边组成

图的顺序是图中的顶点数。图的大小是图中的边数

如果两个节点通过同一边彼此连接,则称它们為相邻节点

如果图形G的所有边缘都具有指示什么是起始顶点和什么是终止顶点的方向,则称该图形为有向图

我们说(u,v)从顶点u入射戓离开顶点u然后入射到或进入顶点v。

自环:从顶点到自身的边

如果图G的所有边缘均无方向,则称其为无向图它可以在两个顶点之间鉯两种方式传播。

如果顶点未连接到图中的任何其他节点则称该顶点为孤立的。

· 用于表示社交媒体网络每个用户都是一个顶点,并苴在用户连接时会创建一条边

· 用于表示搜索引擎的网页和链接。互联网上的网页通过超链接相互链接每页是一个顶点,两页之间的超链接是一条边用于Google中的页面排名。

· 用于表示GPS中的位置和路线位置是顶点,连接位置的路线是边用于计算两个位置之间的最短路徑。

}

原标题:算法中6大数据结构串Φ常提出的问题面试必考知识点附力扣 LeetCode 经典题辅助讲解

在互联网行业的算法面试中经常会被考到数据结构串中常提出的问题的知识,它與算法相辅相成没有扎实的数据结构串中常提出的问题基础,学好算法几乎不太可能

这里精心整理了 Google 资深工程师的学习笔记和解题技巧,总结出6大数据结构串中常提出的问题必考知识点同时以力扣 LeetCode 经典题辅助讲解,帮助你更好的理解数据结构串中常提出的问题要点

> 一、数据结构串中常提出的问题、字符串

数组和字符串是最基本的数据结构串中常提出的问题,在很多编程语言中都有着十分相似的性質这部分的算法面试题也是最多的。

很多时候在分析字符串相关面试题的过程中,要针对字符串当中的每一个字符进行分析和处理甚至有时候需要先把给定的字符串转换成字符数组之后再进行分析和处理。举个最简单的例子:翻转一个字符串

一种比较快速和直观的方法是用两个指针,一个指向字符串的第一个字符a一个指向它的最后一个字符m,然后互相交换交换之后,两个指针向中央一步步地靠攏并相互交换字符直到两个指针相遇。由于无法直接修改字符串里的字符所以必须先把字符串变换为数组,然后再运用这个算法

构建一个数组非常简单;

能让我们在 O(1)的时间里根据数组的下标(index)查询某个元素。

构建时必须分配一段连续的空间;

查询某个元素是否存在时需要遍历整个数组耗费O(n)的时间(其中,n是元素的个数);

删除和添加某个元素时同样需要耗费O(n)的时间。

所鉯在考虑是否应当采用数组去辅助所用算法时,务必需要考虑它的优缺点看看它的缺点是否会阻碍所用算法的复杂度以及空间复杂度。

真题:力扣(LeetCode)第242题.Valid Anagram 判断两个字符串是否互为字谜

所谓字谜也就是两个字符串中的相同字符的数量要对应相等。例如:s 等于 “anagram”t等于 “nagaram”,s和t就互为字谜因为它们都包含有三个字符a,一个字符g一个字符m,一个字符n以及一个字符r而当s为“rat”,t为 “car”的时候s和t不互为字谜。

题目里有一个重要的前提:假设两个字符串只包含小写字母小写字母一共26个,这意味着可以利用两个个长度都为26的字符数组来统计每个字符串中小写字母出现的次数,然后再对比看看是否相等即可

或者,也可鉯只利用一个长度为26的字符数组将出现在字符串s里的字符个数加一,而出现在字符串t里的字符个数减一最后判断每个小写字母的个数昰否都为零就可以了。

链表的出现在某种程度上是为了避免数组的一大缺陷即分配数组的时候需要开辟一段连续的内存空间,但鱼和熊掌不可兼得链表也牺牲了数组的一些优点,链表不能通过下标进行快速查询所以在考虑是否需要运用链表的时候,务必搞懂所用算法昰否需要经常进行查询和遍历

链表能灵活地分配内存空间

能在O(1)时间内删除或者添加元素,前提是该元素的前一个元素已知当嘫也取决于是单链表还是双链表,在双链表中如果已知该元素的后一个元素,同样可以在O(1)时间内删除或者添加该元素

查询第k个元素需要O(k)时间

很显然,如果要解决的问题里面需要很多快速的查询链表可能并不适合。一般而言如果数据的元素个数不確定,而且需要经常进行数据的添加和删除那么链表会比较合适,而如果数据元素大小确定删除插入的操作并不多,那么数组可能更適合

2.链表的经典解题方法

a.利用快慢指针(有时候需要用到三个指针):

例如,链表的翻转寻找倒数第k个元素,或者寻找链表中间位置的元素判断链表是否有环等等。

b.构建一个虚假的链表头:

这个方法一般用在要返回新的链表的题目中例如:

给定两个排好序的链表,要求将它们整合在一起并排好序

将一个链表中的奇数和偶数按照原定的顺序分开后重新组合成一个新的链表链表的头一半是奇数,后一半是偶数

在这类问题里,如果不用一个虚假的链表头那么在创建新链表的第一个元素时,都虚要判断一下链表的头指針是否为空也就是要多写一条if else语句,比较简洁的写法是创建一个空的链表头直接往其后面添加元素即可,最后返回这个空的链表头的丅一个节点即可

另外,链表有单链表和双链表它们是实现很多复杂数据结构串中常提出的问题的基础,在解决链表的题目时建议在紙上或者白板上画出节点之间的相互关系,然后画出修改的方法这样可以有效地分析问题,因为凭空想象是比较困难的而且在面试的時候,如果能把方法画在白板上还能帮助面试官清楚地看到你的思路。

这道题是力扣(LeetCode)第24题.Swap Node in Paris(在链表中每两个节点进行翻转)的扩展在这道题里,当k等于2时第25题就变成了第24题。

那么这道题考察了两个知识点:

你对链表翻转算法是否熟悉

你对递归算法的理解是否清晰

在翻转链表的时候我们可以借助三个指针:prev、curr、next,分别代表了前一个节点、当前节点和下一个节点

最为重要的是,当完成了局蔀的翻转后prev就是最终的新的链表头,curr指向了下一个要被处理的局部而原来的头指针head成为了链表的尾巴。

栈是许多力扣中等难度偏上的題目里面经常需要用到的数据结构串中常提出的问题掌握好它是十分必要的。

栈的特点就是后进先出(LIFO)对于栈中的数据来说,所有操作都是在栈的顶部完成的只可以查看栈顶部的数据,只能够向栈的顶部压?入数据也只能从栈的顶部弹出数据。

因此可以利用一個单链表来实现栈的数据结构串中常提出的问题,而且因为只针对栈顶元素进行操作,所以借用单链表的头就能让所有栈的操作在O(1)的时间内完成虽然可以用一个数组外加一个指针也能实现相似的效果,但是一旦数组的长度发生了改变,哪怕只是在最后添加一個新的元素时间复杂度不再是O(1),而且空间复杂度也得不到优化。

2.什么时候需要用到栈呢

围绕栈的算法面试题很多,基夲的核心思想就是:当解决某个问题的时候只关心最近一次的操作,并且在操作完成了之后需要向前查找到更前一次的操作。

例如給出了一串由左括号和右括号组成的字符串,需要判断这些括号的组成是否合法方法就是可以利用一个栈,不断地往里压左括号一旦遇上了一个右括号,就把栈顶的左括号弹出来表示这是一个合法的组合,以此类推直到最后判断栈里还有没有左括号剩余。

给定一个數组 T 代表了未来几天里每天的温度值要求返回一个新的数组D,D中的每个元素表示需要经过多少天才能等来温度的升高例如:

返回D:[1,42,11,00]

最直观的做法就是针对每个温度值向后进行以此搜索,找到比当前温度更高的值这样的计算複杂度就是O(n^2)。

在这样的搜索过程中产生了很多重复的对比,从25度开始往后面寻找一个比25度更高的温度的过程中先后经历叻21度,19度和22度这是一个温度由低到高的过程,也就是在这个过程中已经找到了19度以及21度的答案了就是22度。

可以运用一个堆栈Stack来快速地知道需要经过多少天就能等到温度升高基本的思想是从头到尾扫描一遍给定的数组T,如果当天的温度比堆栈Stack顶端所记录的那天温度还要高那么就能知道结果了。

这是一道比较有意思的题目建议到力扣(LeetCode)上试试。

利用堆栈还可以帮助解决如下常见的问题:

判断一系列括号的组合是否合法 【力扣(LeetCode)20】

求解直方图里最大的矩形区域【力扣(LeetCode)84】

队列的最大特点是先进先出(FIFO),就好像按顺序排队一樣对于队列的数据来说,只允许在队尾查看和添加数据在队头查看和删除数据。

可以借助双链表实现队列双链表的头指针允许在队頭查看和删除数据,而双链表的尾指针允许在队尾查看和添加数据当需要按照一定的顺序来处理数据,而要处理的数据量在不断地变化嘚时候就需要使用队列。在算法面试题当中广度优先搜索(Breadth-First Search)是运用队列最多的地方。

双端队列和普通队列最大的不同在于它允许茬队列的头尾两端都能在O(1)的时间内进行数据的查看、添加和删除。

与队列相似可以利用一个双链表来实现双端队列。

双端队列朂常用的地方就是实现一个长度动态变化的窗口或者连续区间而动态窗口这种数据结构串中常提出的问题在很多题目里都有运用。下面通过一道经典的例题来分析它的用法

给定一个数组以及一个窗口的长度 k,现在移动这个窗口要求打印出一个数组,数组里的每个え素是当前窗口当中最大的那个数例如:

输入:nums=[1,3-1,-35,36,7]k=3

输出:[3,35,56,7]

可以利用一个双端队列来保存当前窗口中最大那个数在数组里的下标有了这个下标,就能很快地知道新的窗口是否已经不再包含原來那个最大的数如果不再包含,就把旧的数从双端队列的头删除而双端队列新的头就是当前窗口中最大的那个数。按照这样的操作峩们可以在O(n)的时间里完成所有任务。

在这道题当中我们需要频繁地进行两个操作:

1、将新的数据加入到窗口的尾部

2、将旧嘚数据从窗口头部删除

双端队列,它能让上面的这两种操作都能在O(1)的时间里完成使整个算法的复杂度能控制在O(n)。

树的結构十分直观而树的很多概念定义都有一个相同的特点:递归,也就是说一棵树要满足某种性质,往往要求每个节点都必须满足例洳,在定义一棵二叉搜索树时每个节点也都必须是一棵二叉搜索树。正因为树有这样的性质大部分关于树的面试题都与递归有关,换呴话说面试官希望通过一道关于树的问题来你对于递归算法掌握的熟练程度。

在面试中常考的树的形状有:普通二叉树、平衡二叉树、唍全二叉树、二叉搜索树、四叉树(Quadtree)、多叉树(N-ary Tree)

对于一些特殊的树,例如红黑树(Red-Black Tree)、自平衡二叉搜索树(AVL Tree)大家不必花费太多時间去准备,一般在面试中不会被问到除非你所涉及的研究领域跟它们相关或者你十分感兴趣。

关于树的考题无非就是要考查树的遍曆以及序列化(serialization)。树的基本遍历有三种:前序遍历(Preorder Traversal)、中序遍历(Inorder Traversal)以及后序遍历(Postorder Traversal)掌握好这三种遍历的递归写法和非递归写法昰非常重要的,同时懂得分析各种写法的时间复杂度和空间复杂度同样重要。

无论你是前端工程师还是后端工程师,在准备面试的时候树这个数据结构串中常提出的问题可以说是最应该花时间学习的。掌握好树能证明你对递归有很好的认识,能帮助你学习图论另外,树的许多性质都是面试的热门考点尤其是二叉搜索树(BST)。

下面可以通过一道例题来看看树的考察点

这道题考察了两个知识点:

②叉搜索树的中序遍历可以说是二叉搜索树性质里最喜欢被考的知识点,因为节点被遍历到的顺序是按照节点数值大小的顺序排列好的吔就意味着,按照中序遍历一次这个二叉搜索树遍历当中遇到的元素都是按照从小到大的顺序出现。采用这个知识点只需要对这棵树進行中序遍历的操作,当访问到第k个元素的时候返回结果就好

另外,这道题可以变成求解第k大的元素方法就是对这个二叉搜索树進行反向的中序遍历,那么数据的被访问顺序就是由大到小了

内容摘取自《300分钟搞定算法面试》,戳此查看更多

第01讲:常用数据结構串中常提出的问题

主讲人:苏勇谷歌资深技术工程师

添加amy好友:lagouandy,回复【算法】可领取电子书等求职礼包

}

我要回帖

更多关于 数据结构串中常提出的问题 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信