链表专题汇总

一文搞懂链表

前言:之前考研的时候因为基础不扎实,所以算法题大多靠背,but 熟练度是一方面,总结方法也要跟上,这样才能起到举一反三的效果。
tips:如果不知道思路,可以先举一个例子模拟一下

方法论

1、虚拟头节点:建一个虚拟节点更让容易表示节点,这样链表的每个节点都是公平的,对于空链表也更好处理
2、 快慢指针(特别注意slow指针,一般要的是它的位置):

  • 寻找/删除单链表(正数、倒数)第 K个(中间)结点,删除增加等某个位置的节点,也都是基于先找到这个节点(有很多题目虽然没有指明要找第k个,但可以转化,比如链表向右移k位,其实就是找倒数k+1的位置)
  • 找两个链表的是否相交,并找出公共入口(这个是双指针 不是快慢指针)
  • 链表环的问题(是否有环、找环的入口)
  • 判断回文列表(找到中间节点,逆置后半部分 然后判断前后两部分是否一致)
  • 有序链表化为平衡的BST(断开链表 三指针—找到中间节点的前后节点)

3、递归

  • 翻转链表—部分翻转、全部翻转(递归 / 迭代)
  • 删除链表中给定值val的【所有、重复】元素(用迭代和递归都可)
  • 交换链中相邻节点
  • 合并两个有序链表
  • 合并k个有序链表

4、头插法、尾插法
尾插法:顺序构造链表(给定数组)
头插法:
逆序构造链表
给定单向链表的头指针和一个节点指针,定义一个函数在 O(1) 内删除这个节点。

5、特殊情况:
链表有0、1、2个节点的情况需要特别考虑(算法开头单列为一种情况)
(删除、插入、寻找的时候 即使是长链,也要考虑被操作对象是头节点、尾节点的情况,一般要定位某节点前节点的指针)
6、快慢指针的slow节点的位置问题

  • 如果链表长度为奇数,当 fast.next = null 时,slow 为中间结点 在这里插入图片描述

  • 如果链表长度为偶数,当 fast = null 时,slow 为中间结点,fast.next.next=null的时候是slow(偶数中间的前一个节点)
    在这里插入图片描述

题目解析

剑指 Offer 06. 从尾到头打印链表

  • 注意事项:如何把栈里面的数添加到数组里面,
    sta.size()
    新建一个size的栈,用for循环填充data[i]

两个链表的公共节点 简单

链表 ——快慢指针/双指针

判断链表是否有环 141

  • 快慢指针是否相遇
  • 考虑有环无环的临界情况 无环fast.next!=null 有环fast!=null

找出环形链表的入口节点 142

  • 首先找到meetingnode
    (快慢指针在圈里面循环最后一定会相交,并且是在慢指针的第一圈)
  • 制造二次相遇:重新定义两个指针,一个指针指向head, 一个指针指向快慢指向的相遇点,然后这两个指针不断遍历(同时走一步),当它们指向同一个结点时即是环的入口结点

判断回文链表 234

  • 快慢指针找到中间节点(找的是偶数靠前的中间节点,以及奇数的中间节点)
    (奇数:fast.next!=null 偶数:fast.next.next!=null)
  • 翻转后面的节点(翻转链表函数 递归迭代)
  • 两个链表逐个比较

重排链表 l1-ln-l2… 143跟回文链表很类似

  • 思路: 把后半部分倒置 把第二个链表分别插入前半部分
  • 找到中间节点(分别考虑,偶数是前边那个节点 奇数就是中间那个节点)
  • 翻转 l2, 断链
  • 插入 (暂存second节点 ,改变指针,更新节点

交换链表中的节点
N14 链表中倒数最后k个结点
旋转平移链表 61

  • 双指针找位置+简单指针变化(注意k有可能大于链的长度)
  • 找到倒数k-1的位置(slow)fast先走k步(用具体的数来k)
  • 断链 、连接

删除链表的倒数第 n 个节点 19

  • 双指针
  • 注意删除头结点的情况

分隔链表(按照给定的值x) 86

  • 思路:分成两个链表,一个小于l1,剩下的挂到另一个l2
  • 由于第一个节点不确定 ——利用dummynode标注l1、l2 头节点
  • 使用node1、node2 标注两个链表尾节点(注意新链表的指向和指出的指针都要处理)

链表元素按奇偶位置聚集 328

  • 双指针+辅助指针:
    odd和even (遍历双指针)
    evennode连接时使用指针,直接返回head
  • 更新操作
    odd.next=odd.next.next;//连接奇链表的下一个
    odd=odd.next;//更新头结点

递归/迭代

递归——链表的地位都相同
(比如反转链表,各个节点的地位就是平等的不影响的)
迭代——链表的地位不同,一般配合dummynode
(比如删除重复元素,一个元素的值会影响其他元素的地位)

合并两个有序链表 21
合并k个排序链表 23

  • 合并两个 ,决定头节点 递归
  • 合并k个,0、1个链表的时候,两个及以上的时候(for循环 lists[i])

剑指offer18. 删除链表的节点(节点值不重复,只删除给定值)
移除链表特定值的元素 203

  • 递归(先递归删除后边的,再判断头节点,不用dummynode)
  • 迭代(使用dummynode,cur,找到cur.next=val 删除就好)(删除链表中的重复元素2)

82. 删除排序链表中的重复元素 II

  • 迭代
  • 使用dummy节点,操作dummy节点指针,删除后边的元素,使用cur遍历
  • 后两个元素不相等(直接cur.next 更新)
  • 相等 直接用一个x代表val ,删除所有x的节点

删除排序链表中的重复元素 83

  • 迭代(两种情形,=删 ≠跳过)
  • 思路:定义slow=head fast=head.next,

N15 反转链表

  • 迭代 (注意定义两个变量节点,注意头尾)
  • 递归(把头节点和递归翻转之后的关系处理好)
    (思想是自上而下,链表的递归是所有节点重要性一致,把后边的当成一个节点,头节点当成一个节点)

两两交换链表中的节点//反转链表 24、206

  • 递归 跟反转差不多,firstnode.next是递归结束之后的值
  • 迭代
    在这里插入图片描述

反转链表(反转指定位置的链表)92

  • 跟反转链表一样,直接迭代或者循环直接改变指针。

排序

对链表进行插入排序 147

O(nlogn) 时间复杂度排序链表148

  • 归并排序
    找中点(快慢指针)
    断链
    分别排序(调用主函数)
    两链表合并(merge子函数)

两个链表

合并两个有序链表 21
合并k个排序链表 23

  • 合并两个 ,决定头节点 递归
  • 合并k个,0、1个链表的时候,两个及以上的时候(for循环 lists[i])

两数相加(两个链表求和 个位数在左边 不需要用栈)2

  • 维护一个t为两节点相加的值,通过dummynode % / t=0 来新建一个链表
  • 用sum来记录两个链表的和
  • new的Listnode的值是sum%10
  • sum/10 !=0 继续new节点

两个链表求和 (个位数在右边 需要用栈)445

1 判断回文链表 234
有序链表转化为平衡的BST 109
链表的中间节点 876
链表中间节点的应用
2 删除链表的倒数第 n 个节点 19
 N14 链表中倒数最后k个结点
 删除排序链表中的重复元素 83
 删除排序链表中的重复元素 II 82
 删除链表的节点(节点值不重复,只删除给定值)面试题18
3 两两交换链表中的节点//反转链表 24、206
旋转链表 61
反转链表(反转指定位置的链表)92
4 合并两个有序链表 21 剑指 Offer 25
 合并k个排序链表 23

5 分隔链表 725
6 两个链表求和 (个位数在右边 需要用栈)445
两链表求和(个位数在左边无需用栈) 2
7 链表元素按奇偶位置聚集 328
分隔链表 (相对于给定值的大小)86
8 判断链表是否有环 141
 找出环形链表的入口节点 142
找出两个无环链表的焦点 160

10对链表进行插入排序 147
11 复杂链表的复制(牛客)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值