5.链表常见操作

作者: 偷天神猫 | 来源:发表于2015-08-12 13:40 被阅读411次

推荐大家看下《编程之美》《程序员面试金典》
还有编程相关网站:leetcode
老师讲的很多题其实就是这些书和网站的题

单链表是否存在环?环的入口是什么?

是否存在环

  1. 判断是否存在环:设置快慢指针fast和slow,fast步速为2,slow为1,若最终fast==slow,那么就证明单链表中一定有环。如果没有环的话,fast一定先到达尾节点

  2. 简单证明:利用相对运动的概念,以slow为参考点(静止不动),那么fast的步速实际为1,当fast超过slow之后,fast以每步一个节点的速度追赶slow,如果链表有环的话,fast一定会追赶到slow,即fast==slow。

如何找到环的入口

第一次相遇第一次相遇

字母代表的量:

  • a:链表头结点到环入口的距离
  • r:环长
  • 蓝色线:fast指针所走的距离2s
  • 黑色线:slow指针所走的距离s

假设链表总长度为L,且fast与slow相遇时fast已经绕环走了n圈,则有如下关系:

2s = s + nr
将s移到左边得:
s = n
r
转换:
s = (n-1)r + r = (n-1)r + L-a
a+x = (n-1)r + L-a
得:
a = (n-1)
r + L-a-x

由图可知,(L-a-x)为相遇点到环入口点的距离。由上式可知:
从链表头到环入口的距离 = (n-1)圈内环循环 + 相遇点到环入口点的距离
将r视为周期的话,a与L-a-x在某种意义上是相等的(实际并不一定相等)。
那么由此我们便找到了突破点,为了找到环的入口点,在fast与slow相遇时,将slow指针重新指向单链表的头节点,fast仍然留在相遇点,只不过步速降为与slow相同的1,每次循环只经过一个节点,如此,当fast与slow再次相遇时,那个新的相遇点便是我们苦苦寻找的入口点了。

如何知道环的长度

纪录下相遇点,让slow与fast从该点开始,再次碰撞所走过的操作数就是环的长度r。

带环的链表的长度是多少?

通过以上分析我们已经知道了如何求环入口,环长,那么链表长度显然就是两者之和,即:
L = a + r

判断两个链表是否相交

分析问题之前我们要搞清楚链表相交的一些基本概念

  • 明确概念:两个单向链表相交,只能是y型相交,不可能是x型相交。
  • 分析:有两个链表,La,Lb,设他们的交点设为p,假设在La中,p的前驱为pre_a,后继为next_a,在Lb中,前驱为pre_b,后继为next_b,则
    pre_a->next=p,pre_b->next=p,接下来看后继,p->next=next_a,p->next=next_b;那么问题就出来了,一个单链表的next指针只有一个,
    怎么跑出两个来呢,所以必有next_a==next_b,于是我们得出两个链表相交只能是Y型相交。明确了这个概念,我们再来堆相交问题进行分析。

情况一:两个链表都无环

  1. 问题简化。将链表B接到链表A的后面,如果A、B有交点,则构成一个有环的单链表,而我们刚刚在上面已经讨论了如何判断一个
    单链表是否有环。
  2. 若两个链表相交则必为Y型,由此可知两个链表从相交点到尾节点是相同的,我们并不知道他们的相交点位置,但是我们可以遍历得出A、B链表的
    尾节点,如此,比较他们的尾节点是否相等便可以求证A、B是否相交了。

情况二:链表有环

  1. 其中一个链表有环,另外一个链表无环。则两个链表不可能相交。(啥?你不知道为啥?自己看看前面的“明确概念”反省吧)

  2. 那么有环相交的情况只有当两个链表都有环时才会出现,如果两个有环链表相交,则他们拥有共通的环,即环上任意一个节点都存在于
    两个链表上。因此,通过判断A链表上的快慢指针相遇点是否也在B链表上便可以得出两个链表是否相交了。

求相交链表的相交点

题目描述:如果两个无环单向链表相交,怎么求出他们相交的第一个节点呢?

分析:采用对齐的思想。计算两个链表的长度 L1 , L2,分别用两个指针 p1 , p2 指向两个链表的头,然后将较长链表的 p1(假设为 p1)向后移动L2 - L1个节点,然后再同时向后移动p1 , p2,直到 p1 = p2。相遇的点就是相交的第一个节点。


相关文章

  • 5.链表常见操作

    推荐大家看下《编程之美》、《程序员面试金典》 还有编程相关网站:leetcode老师讲的很多题其实就是这些书和网...

  • 链表

    文章结构 链表的定义 链表的插入和删除操作 链表的特性 常见的链表结构 自定义链表 链表的经典操作 使用链表实现L...

  • 链表常见操作

  • 链表常见操作

    7.3.1 链表的概念1、链表的结构 又分为带头结点和不带头结点,头结点一般称为head,data不存放任何内容,...

  • Java常用类库与技巧-集合

    一 数据结构常见问题 数组和链表的区别;链表的操作,如反转,链表环路检测,双向链表,循环链表相关操作;队列,栈的应...

  • 5.常见操作

    安装 hexo-server npm install hexo-server --save 启动服务 hexo ...

  • 常见的链表操作

    单链表反转 思路 迭代:在遍历列表时,将当前节点的 next 指针改为指向前一个元素。由于节点没有引用其上一个节点...

  • 链表

    链表和数组一样也支持查找,插入,删除操作。最常见的三种链表是:单链表,双链表和循环链表。 链表和数组的区别:数组需...

  • 链表(Java)

    链表常见的操作: 1、插入节点(头插、尾插)2、删除节点3、获取链表长度4、逆序打印5、反转链表6、判断链表是否有...

  • 数据结构-单链表学习目录

    1.单链表的基本操作 2.求单链表的长度 3.判断单链表是否为空 4.查找单链表中倒数第K个结点 5.单链表的反转...

网友评论

    本文标题:5.链表常见操作

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