算法题心得 - 链表

上篇文章介绍了数组,哈希表,字符串相关的算法,这篇文章介绍另一个重要的数据结构,链表

链表特点

链表,和数组相比较的话,对于存储空间更加灵活,不像是数组,必须要求连续的空间,而且在数组中删除一个元素,就比较麻烦了,严格而言,删除数组中的一个元素,需要将后面的所有元素都向前移动。但是数组这种数据结构也有特别优秀的特点,就是查找的时间复杂度是O(1)。链表对存储空间很灵活,不要求连续,删除一个节点,只需要从整个链表中去掉就可以了。但是缺点就是查找的时间复杂度为O(n)。因此,究竟要用数组还是链表,要看项目的实际情况。

链表的节点可以理解为以下结构

struct _Node;
typedef struct _Node {
struct _Node* next_;
} Node;

可以发现,链表结构体中有一个指向下一个节点的next_,这也就是链表成链的关键。因此链表很容易考察对指针的理解,而指针,也就是处理链表相关问题的关键。

典型算法题

典型的算法题如面试题23:链表中环的入口节点

题目:如果一个链表中包含环,如何找出环的入口节点?

这是一道典型的链表题。上面分析过,解决链表类问题,最关键的就在于指针。对于这类问题,我们往往用两个指针,这两个指针可以从相同的节点出发,也可以从不同的节点出发,可以两指针的速度相同,也可以速度不同,巧妙的运用这些技巧,就可以解决一些复杂的问题。

比如解决这个问题,就需要类似的技巧。首先要对问题进行分解。对于复杂的问题,我们要想办法将其分解为简单的问题。比如这个问题,就可以做如下分解:如何判断链表中有环?如果有环的话,如何得到链表中环的个数?最后就是如何找到环的入口点?

判断链表成环

首先解决第一个问题,就是如何判断链表中有环。什么情况下有环呢?就是其中某一个节点,他的下一个节点又指向了前面的节点,如此一来,这个链表,就永远找不到结尾了。就好像是一个跑道,一直在绕着圈跑,却永远跑不到终点。有了这种启发,我们是不是可以判断链表的next有没有终止呢?如果从头开始遍历节点,如果某个节点的next_为nullptr,自然,就是没有成环的链表。如果找不到next_为nullptr的节点,则就是成环的链表。这是一个基本的思路,但是如果判断的条件是

while (node_->next_ != nullptr) {
node_ = node_->next_;
}
// 如果代码走到这里说明没有成环

这种判断有一个致命的错误,就是在成环的链表中,while的判断条件永远是true的,因此这个while循环是退出不了的。这当然是不可容忍的。如何让while循环可以停止呢?也就是如何在成环的条件下找到停止的条件呢?这就需要用到刚才提到过的双指针方法。其实思想非常简单,比如两个人赛跑,如果跑的快的那个人追上跑的慢的人,则跑道肯定成环。有了这种思想,我们定义两个指针,这两个指针都从链表的head开始跑,一个指针每次跑一个节点,另一个指针每次跑两个节点,这就是两个指针从相同的位置,但是速度不同的典型用法。如果一次跑两个节点的那个指针,碰到了node_->next_ == nullptr的情况,则说明链表不成环。如果一次跑两个节点的那个指针,追上了一次跑一个的那个指针,则说明链表成环。

确定链表环个数

下面我们来解决第二个问题,就是得到链表环中的个数。有了上一步的结果,如果成环的话,快指针会追上慢指针。追上的那个节点,肯定是环内的某个节点。我们可以从这个节点开始计数,让指针从这个节点开始出发,每次走一个节点,没走一个节点,计数增加。由于这个指针是环内的某个节点,因此,这个指针一定会回到他出发的地方。当他再次回到起始的节点时,我们统计的计数,就是环内节点的个数。

确定链表环起始节点

有了前面的结论,我们已经知道链表是否成环,如果成环的话,环内节点个数也清楚了。现在让我们找到环的起始节点。这里,我们还需要运用双指针的技巧,假设我们已经知道了环内的个数为k,我们可以定义两个指针,其中一个指针从头开始出发,另一个指针从第k个节点开始出发,两个指针每次往前走一个节点,当两个节点相遇的时候,就是环内的第一个节点。

小结

从上面的典型面试题可以看出,解决链表类问题,灵活的使用指针是关键,特别的,我们经常会使用双指针的技巧,两个指针可以从同一个节点出发,速度不同,也可以从不同的节点出发,速度相同等等。灵活的使用这些技巧,可以解决一些复杂的链表问题。特别的,对于任何复杂的问题,我们都要将其积极的拆分为简单的问题。这样才能化繁为简,一步一步的解决问题。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容

  • //leetcode中还有花样链表题,这里几个例子,冰山一角 求单链表中结点的个数----时间复杂度O(n)这是最...
    暗黑破坏球嘿哈阅读 1,509评论 0 6
  • 搞懂单链表常见面试题 Hello 继上次的 搞懂基本排序算法,这个一星期,我总结了,我所学习和思考的单链表基础知识...
    醒着的码者阅读 4,572评论 1 45
  • 链表删除[203] Remove Linked List Elements[19] Remove Nth Node...
    野狗子嗷嗷嗷阅读 6,256评论 4 35
  • 我坐在电脑前,准备浏览单位的网页,看看有没有最新的消息,于是晃动鼠标,唤醒屏幕,屏幕上出现了昨天打开但还未浏览...
    守护的狗阅读 150评论 0 1
  • 今日赴林州对农村改革工作进行调研,一路景致妖娆,令人陶醉。大山巍峨,蓝天如海,白云悠悠,秋色醉人。 ...
    太行客阅读 382评论 0 0