链表和双指针框架

Posted Debroon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表和双指针框架相关的知识,希望对你有一定的参考价值。

链表和双指针框架

 


链表遍历和左右指针框架

力扣的链表问题,基本都是单链表。

单链表的操作难点在于,缺了指向前一个节点的指针,而链表删除结点是通过待删除结点的前一个结点。

在力扣里,是让遍历的指针p,从指向【当前节点】改成指向【前一个节点】,这样就有了指向前一个节点的指针。

每次查看节点从 p 变成 p.next,循环终止条件从 p == NULL 变成 p.next==NULL

这样操作比较别扭且容易出错,而且力扣主要是考算法设计,C++语言特性的二级指针、创建额外的哨兵节点都不能用。

我们寻找一种更通用的设计方法,这称为【链表和左右指针遍历框架】。

  • 双指针技巧主要分为两类:左右指针和快慢指针。
  • 左右指针,就是两个指针相向而行或者相背而行。
  • 快慢指针,就是两个指针同向而行,一快一慢,滑动窗口也是快慢指针。

当删除链表结点时,既需要访问当前结点,也需要访问前一个结点。

就使用两个指针来遍历链表,curr 指针指向当前结点,prev 指针指向前一个结点。

这样两个指针的语义明确,也让你写出的代码更易理解。

ListNode pre = null;      // 辅助指针,记录 cur 的上一个值
ListNode cur = head;      // 主指针,cur 表示当前结点
while (cur != null)    
    if (pre == null)     // cur 是头结点时的操作
    
     else               // cur 不是头结点时的操作
    
    
    pre = cur;            // 循环中始终维护 pre 是 curr 的前一个节点
    cur = cur.next;       // 更新 cur

使用链表和双指针遍历框架:

  • 判断问题是否为链表遍历-修改,如果是,套用链表遍历框架
  • 思考单步操作,将代码加入遍历框架

例题:

 


链表逆向遍历和快慢指针

链表数据类型的特点决定了它只能单向顺序访问,而不能逆向遍历或随机访问。

我们需要使用快慢指针的技巧来实现一定程序的逆向遍历,能减少重复遍历次数,这也是为什么快慢指针常用于链表问题。

自定义返回类型 middleNode(ListNode head) 
    ListNode slow = head, fast = head;           // 快慢指针初始化指向 head
    while (fast != null && fast.next != null)   // 快指针走到末尾时停止
        slow = slow.next;                        // 慢指针走一步
        fast = fast.next.next;                   // 快指针走两步
    
    return 自定义返回内容;                         // 快指针在终点,慢指针在中点

例题:

 


链表处理细节

细节1:创建额外的哨兵节点的时机

当需要创造一条新链表的时候,可使用虚拟头结点简化边界情况的处理。

例题:

  • 21.合并两个有序链表,把两条有序链表合并成一条新的有序链表。
  • 86.分隔链表,把一条链表分解成两条链表。

细节2:链表递归顺序

void traverse(ListNode root)     // 递归遍历单链表
    if (root == null) return;     // 最基础的情况
    print(root.val);              //【前序位置】
    traverse(root.next);
    print(root.val);              //【后序位置】

前序位置和后序位置的区别是什么?

  • 前序位置的 print(root.val):遍历链表,沿途输出节点,顺序遍历
  • 后序位置的 print(root.val):遍历链表,一直遍历,直到遇到最基础的情况才能计算出子问题的解,逆序遍历。
     

细节3:虚拟节点

细节4:穿针引线

细节5:先穿后排,再判空

以上是关于链表和双指针框架的主要内容,如果未能解决你的问题,请参考以下文章

动态链表和静态链表

单向链表和二进制

c语言链表和指针的运用

静态链表和动态链表的区别

C语言中链表与队列有很么区别?

[读书笔记]-大话数据结构-3-线性表-静态链表循环链表和双向链表