链表#简单#反转链表
链表#简单#反转链表
前文
给你单链表的头节点head
,请你反转链表,并返回反转后的链表。
1
2
3
4
5
6
7
8
9
示例 2:
输入:head = [1,2]
输出:[2,1]
示例 3:
输入:head = []
输出:[]
正文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
}
};
解法1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while (curr) {
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
创建一个标识为前一个的prev
和标识为当前的curr
指针,curr
指针最开始当前为head
, 如果当前指针不是空指针,循环当前指针,循环过程为: 找到当前指针的下一个并存储为next
,将prev
指针赋给当前指针的下一个, 此时因为刚刚已经用next
存储了当前指针的下一个,所以下一个指针还在, 此时将当前指针赋给prev
,然后将next
赋给当前指针curr
。
过程演示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 设链表为:
1->2->3->4->nullptr
// 其中格式意思是 x, 0xaddress,前一个是值,后一个0x表示值为x的地址
开始时 head = 1->2->3->4->nullptr
进入函数:
prev = nullptr
curr = head = 0x1
循环:
// 下方为开始时
next = curr->next // 即 next = 2->3->4->null
curr->next = prev // 即 1->next = null
prev = curr // 即 prev = 1->null
curr = next // 即 curr = 2->3->4->nullptr
// 进入下一个循环:
// next = 3->4->null
// 2->next = 1->null
// prev = 2->1->null
// curr = 3->4->nullptr
// ... 依次类推
解法2 递归
本质上,反转链表需要将后一个元素指向之前的元素,即每次第一个元素指向之前的元素。 同时存储之前元素,因此递归也可以很好解决:
1
2
3
4
5
6
7
8
9
10
11
ListNode* reverse1(ListNode *prev, ListNode *curr) {
if (curr == nullptr)
return prev;
ListNode* next = curr->next;
curr->next = prev;
prev = curr
return reverse1(prev, next);
}
reverse1(nullptr, head);
递归中,每次将当前元素的下一个指向之前元素,同时递归下一个元素。
1
2
3
4
5
递归第一次:
1->nullptr,递归(1->nullptr, 2->3->4->nullptr)
递归第二次:
2->1->nullptr,递归(2->1->nullptr, 3->4->nullptr)
依次直到递归至nullptr,即反转完成
本文由作者按照 CC BY 4.0 进行授权