【算法刷题】链表题型及方法归纳

链表特点

种类:单链表、双链表和循环链表
主要特点:
(1)存储空间不一定连续,通过指针链接在一起
(2)删除、添加方便,查找麻烦。

链表定义

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

链表遍历
常用pre、cur、temp三个指针实现遍历、删除和交换。其中pre指向节点的前驱指针,cur指向当前节点,temp用于临时节点常用来先暂存指向后继节点。

// 用cur遍历
while(cur != NULL) {
    if(cur->val == val) {
        ListNode* temp = cur;
        cur = temp->next;        
        pre->next = cur;        
        delete temp;
    }else{
        pre = cur;
        cur = cur->next;
    }    
}

// 用pre遍历
while(pre->next != NULL) {
	if(pre->next->val == val) {
		ListNode* temp = pre->next;
		pre->next = temp->next;
		delete temp;		
	}else{					// 用else分隔遍历操作
		pre = pre->next;
	}
}

1、采用虚拟头结点

设置虚拟头结点便于对头结点进行增、删操作,不用再专门写一段代码来区分遍历到的是头结点还是其余结点,用同样的增、删代码即可实现。同时,还可以放置链表为空,也减少了程序的复杂性和出现bug的机会。

64、【链表】leetcode——203. 移除链表元素(C++版本)

2、设计链表:基本CRUD操作

基础操作练习:
获取元素、删除元素、添加首、尾、任意位置元素

注意:边界问题,要在符合边界内操作,增删时修改链表长度记录。

√ 65、【链表】leetcode——707. 设计链表(C++、Python版本)

3、反转链表类题型

方法一:
改变指针的指向,设置pre和cur指针实现。初始时pre->NULLcur->head,每遍历一遍就改变一次指向,直至cur->NULL,然后返回pre
分别可用迭代法递归法实现。

方法二:
新创建一个虚拟头结点,采用头插法将原链表中元素加入到新链表中。遍历原始链表,每遍历到一个节点,就用头插法将该节点插入到虚拟头结点的后面。

题目:

  1. temp每次先保存cur后续元素,然后用pre、cur实现反转
    反转链表

  2. 在反转链表的基础上,稍微改动。改变指向[pre,cur]
    两两交换链表中的节点
    (1)边界条件:注意每次是对两个节点进行修改,因此需要判断这两个节点不为空
    (2)使用pre和cur指针实现。pre从dummyHead开始,cur从head开始。每次先保存下一轮待处理元素,然后交换两两元素,再更新起始位置。

4、非等长且需知长度差的链表题型

  1. 快慢双指针方法
    删除链表的倒数第N个节点
    求倒数第n个,先快指针走n步,然后慢指针和快指针再一起走,当快指针走到底时,慢指针就在n。
    **注意:**设置虚拟头结点便于增、删原头结点;注意遍历时是按前指针遍历还是当前指针遍历。

  2. 快慢双指针消除长度差 / 合并链表走
    链表相交
    两种方法:
    (1)求出A和B长度,消除长度差,然后再一起走。
    (2)合并链表走,先走自己再走对方,最后会达到公共交点或者NULL

5、环形链表题型

1.快慢双指针 / 哈希表方法
66、【链表】leetcode——142. 环形链表 II(C++、Python版本)
方法一:
快慢双指针。主要是通过数学证明,得到入口点的特性。分析得出的结论:从相遇点和头节点出发一起走,一定会在某一时刻在入口点相遇。
具体实现:先让快指针以步数为2出发,慢指针以步数为1出发,找到相遇点。再让头结点处和相遇点处指针一起以相同步数出发,在某一时刻会在入口点处相遇。
方法二:
哈希表 / 集合,将节点一次加入到表中,如果再次加入时,发现表中已经存在,则说明到达入口点。

你可能感兴趣的:(数据结构与算法刷题,#,链表,算法,链表,c++)