【LeetCode】3.链表系列

总目录:

LeetCode系列导航目录

像我这样优秀的人,本该灿烂过一生, 这么多天LeetCode刷下来,还在链表里浮沉。

 

0.理论基础

0.1.要点

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

种类:单链表、双向链表、循环链表。

链表在内存中不是连续分布的,不能通过索引访问。

0.2.常见操作

删除节点,跳过指定节点

增加节点,增加新的指向

 

 

 

 

0.3.优缺点

 

 

 

1.问题

1.1.问题描述

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

链接https://leetcode.cn/problems/remove-linked-list-elements/

1.2.要点

头结点的处理是个要点

1迭代,添加虚节点作头节点,返回前再去掉

2递归

1.3.代码实例

迭代

 1 class Solution {
 2 public:
 3     ListNode* removeElements(ListNode* head, int val) {
 4         struct ListNode* dummyHead = new ListNode(0, head);
 5         struct ListNode* temp = dummyHead;
 6         while (temp->next != NULL) {
 7             if (temp->next->val == val) {
 8                 temp->next = temp->next->next;
 9             } else {
10                 temp = temp->next;
11             }
12         }
13         return dummyHead->next;
14     }
15 };
View Code

递归

 1 class Solution {
 2 public:
 3     ListNode* removeElements(ListNode* head, int val) {
 4         //本层逻辑
 5         while(head!=NULL && head->val==val){
 6             head=head->next;
 7         }
 8 
 9         //中止条件
10         if(head == NULL){
11             return head;
12         }
13 
14         //递归调用
15         head->next = removeElements(head->next,val);
16 
17         return head;
18     }
19 };
View Code

 

2.设计链表添加指定功能

2.1.问题描述

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。
在链表类中实现这些功能:
    get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
    addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
    addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
    addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
    deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。
链接:https://leetcode.cn/problems/design-linked-list

2.2.要点

1保存好头节点

2维护好链表长度

2.3.代码实例

 

3.翻转链表

3.1.问题描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

链接https://leetcode.cn/problems/reverse-linked-list/

3.2.要点

双指针,维护好前后关系而已

递归,通过层序来维护前后关系

3.3.代码实例

双指针

 1 class Solution {
 2 public:
 3     ListNode* reverseList(ListNode* head) {
 4         ListNode* cur = NULL, *pre = head;
 5         while (pre != NULL) {
 6             ListNode* t = pre->next;
 7             pre->next = cur;
 8             cur = pre;
 9             pre = t;
10         }
11         return cur;
12     }
13 };
View Code

递归

 1 class Solution {
 2 public:
 3     ListNode* reverseList(ListNode* head) {
 4         if (head == NULL || head->next == NULL) {
 5             return head;
 6         }
 7         ListNode* ret = reverseList(head->next);
 8         head->next->next = head;
 9         head->next = NULL;
10         return ret;
11     }
12 };
View Code

 

4.两两交换链表中的元素

4.1.问题描述

给你一个链表,每两个交换一下位置,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

链接https://leetcode.cn/problems/swap-nodes-in-pairs/

4.2.要点

迭代,略

递归,管理当前的两个节点、下层节点的头节点,然后返回当前两个节点的头节点

4.3.代码实例

迭代,略

递归

 1 class Solution {
 2 public:
 3     ListNode* swapPairs(ListNode* head) {
 4         if (head == NULL || head->next == NULL)  
 5             return head;
 6         ListNode* rest = head->next->next;
 7         ListNode* newHead = head->next;
 8         newHead->next = head;
 9         head->next = swapPairs(rest);
10         return newHead;
11     }
12 };
View Code

 


5.删除链表倒数第n个节点

5.1.问题描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

5.2.要点

2次遍历计算长度,第二次遍历时直接取值

双指针

5.3.代码实例


 

6.找到两个单链表的起始交点

6.1.问题描述

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

链接https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

6.2.要点

双指针,走到头后分别再从对方的起点走起,使两个指针走过相同的路程,从而到达第一个公共点。

哈希,略

6.3.代码实例

 

 

7.找到环形链表的入口节点

7.1.问题描述

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
链接:https://leetcode.cn/problems/linked-list-cycle-ii

7.2.要点

哈希

快慢指针法,数学计算距离,分析入口点的数学特性:

fast每次走2步,slow每次走1步,假设走到b到c的交界处时fast==slow,

fast走过的距离:a+b+c+b,slow走过的距离:a+b,

因为fast速度是slow的2倍,因此a+b+c+b=2*(a+b),得出a=c

此时让fast和slow分别从head和b到c交点处出发,每次都只走一步,再次相交时即为环入口。

7.3.代码实例

 

8.总结

8.1.经典题

虚拟头节点

增、删、取指定序号的节点

翻转链表

倒数第k个节点

链表相交

环形链表

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

xxx.问题

xxx.1.问题描述

111

xxx.2.要点

222

xxx.3.代码实例

333

posted @ 2022-12-12 20:52  啊原来是这样呀  阅读(23)  评论(0编辑  收藏  举报