美文网首页
算法题心得 - 链表

算法题心得 - 链表

作者: bigonelby | 来源:发表于2018-06-20 15:48 被阅读21次

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

链表特点

链表,和数组相比较的话,对于存储空间更加灵活,不像是数组,必须要求连续的空间,而且在数组中删除一个元素,就比较麻烦了,严格而言,删除数组中的一个元素,需要将后面的所有元素都向前移动。但是数组这种数据结构也有特别优秀的特点,就是查找的时间复杂度是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个节点开始出发,两个指针每次往前走一个节点,当两个节点相遇的时候,就是环内的第一个节点。

小结

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

相关文章

  • 算法题心得 - 链表

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

  • Tourist with Data Structure Seco

    链表 读题要仔细,只看题干,容易死的很惨。 设计链表 环形链表 一般环形链表使用快慢指针方式去做,快慢指针算法。参...

  • 数据结构与算法-链表相关题

    数据结构预算法题 正确的解算法题,前提是要正确审题,找出关键词! 题⽬1 : 将2个递增的有序链表合并为⼀个链表的...

  • ARTS 20201208-1215

    Algorithm: 每周至少做一个 LeetCode 的算法题算法题:1 剑指 offer 24: 翻转链表递归...

  • python链表及算法

    实现了python单向链表及一些算法题

  • 希望变得熟练,然后游刃有余

    链表的算法题还是不是很熟啊,虽然今天的反转链表的题已经写的相对熟练了,可是还是不够理解,晚上接雨水这道题倒...

  • leetcode链表之反转链表

    本文主要有三道题,都是关于反转链表的算法题,由浅入深。文章出现的代码都是python3 206、反转链表[http...

  • 数据结构与算法第三讲 - 链表

    本讲内容 链表定义和分类链表和数组比较链表操作写链表代码的技巧简单算法题 链表定义和分类 定义:通过指针把零散的内...

  • 【JS算法】 环形链表双指针

    LeetCood141题给你一个链表的头节点 head ,判断链表中是否有环 通俗易懂的算法 双指针算法 如果是环...

  • 极客时间算法40讲

    简述 极客时间算法40讲中所出现的leetcode算法题 题目 【链表】reverse-linked-list(反...

网友评论

      本文标题:算法题心得 - 链表

      本文链接:https://www.haomeiwen.com/subject/hwkxyftx.html