难度参考
难度:简单
分类:链表
难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。以下内容均为个人笔记,旨在督促自己认真学习。
题目
反转一个单链表(不带头节点)
示例1:
输入:1->2->3->4->5->null
输出:5->4->3->2->1->null
解释:链表反转后顺序逆序,由1->2->3->4->5->null,变成了5->4->3->2->1->null
思路
初始化两个指针:prev 和 current,分别指向当前节点的前一个节点和当前节点。
- 使用一个临时指针
nextNode保存当前节点的下一个节点,以备后续使用。 - 在循环中,将当前节点的
next指针指向prev,实现反转操作。 - 移动
prev和current指针,继续向后遍历链表。 - 重复步骤 3 和 4,直到
current指针指向链表末尾,即current为NULL。 - 返回反转后的链表的头节点,即原链表的末尾节点



示例
理解链表反转可能有些抽象,但可以通过将其拆分成简单的步骤来理解。以下是更具体的步骤和示例,帮助你更好地理解链表反转:
假设我们有一个链表:1 -> 2 -> 3 -> 4 -> 5 -> null
- 初始化两个指针,
prev和current,初始时都指向null。 - 从链表的头部开始遍历,首先处理节点
1:prev指向nullcurrent指向1
- 在每一步中,我们将
current的next指向prev,即将1 -> null变成1 <- null,然后移动指针:prev指向1current指向2
- 重复上述步骤,将每个节点的
next指向前一个节点,直到到达链表末尾:prev指向4current指向5
- 最终,链表变成:5 -> 4 -> 3 -> 2 -> 1 -> null
通过不断将当前节点的 next 指向前一个节点,我们逐步完成了链表的反转。这是链表反转的基本思路。希望这个示例有助于你更好地理解这个过程。
梳理
-
首先,我们定义了一个单链表节点结构
ListNode,其中包括一个整数值val用于存储节点的值,以及一个指向下一个节点的指针next。 -
然后,定义了一个
reverseList函数,它接受一个头节点head作为参数,用于反转单链表。 -
在
reverseList函数中,我们初始化了两个指针prev和current,开始时都指向NULL。prev用于存储当前节点的前一个节点,而current用于表示当前节点。 -
使用
while循环遍历链表,循环条件是current != NULL,即遍历链表直到当前节点为空(链表末尾)。 -
在每次循环中,我们首先保存下一个节点的指针为
nextNode,以备后续使用。 -
然后,将当前节点的
next指针指向前一个节点prev,这样就完成了当前节点指向前一个节点的反转操作。 -
接着,将
prev指针移动到当前节点,为下一轮循环做准备。 -
最后,将
current指针移动到下一个节点nextNode,继续下一轮循环。 -
当循环结束时,
prev指针指向原链表的末尾节点,即反转后的链表的头节点,因此我们返回prev作为反转后链表的新头节点。 -
在
main函数中,我们创建了一个示例链表,然后调用printList函数打印原始链表,再调用reverseList函数进行链表反转,最后再次调用printList函数打印反转后的链表。

代码
#include <iostream>
using namespace std;
// 定义单链表节点结构
struct ListNode {
int val; // 存储节点的值
ListNode* next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 构造函数,初始化节点的值和指针
};
// 反转单链表的函数
ListNode* reverseList(ListNode* head) {
ListNode* prev = NULL; // 初始化前一个节点为NULL,用于存储当前节点的前一个节点
ListNode* current = head; // 初始化当前节点为头节点,从头节点开始反转
while (current != NULL) { // 循环遍历链表,直到当前节点为NULL(即链表末尾)
ListNode* nextNode = current->next; // 保存下一个节点的指针,以备后续使用
current->next = prev; // 反转当前节点的指针方向,使其指向前一个节点
prev = current; // 移动prev指针,指向当前节点,为下一轮循环做准备
current = nextNode; // 移动current指针,指向下一个节点,继续反转操作
}
return prev; // 返回新的头节点,即原链表的末尾节点
}
// 打印链表的函数
void printList(ListNode* head) {
ListNode* current = head; // 从头节点开始遍历链表
while (current != NULL) { // 循环遍历链表,直到当前节点为NULL
cout << current->val << " "; // 打印当前节点的值
current = current->next; // 移动到下一个节点
}
cout << "null" << endl; // 打印链表末尾的null表示链表结束
}
int main() {
// 创建示例链表:1->2->3->4->5->null
ListNode* head = new ListNode(1); // 创建头节点并初始化值为1
head->next = new ListNode(2); // 创建下一个节点并初始化值为2
head->next->next = new ListNode(3); // 创建下一个节点并初始化值为3
head->next->next->next = new ListNode(4); // 创建下一个节点并初始化值为4
head->next->next->next->next = new ListNode(5); // 创建下一个节点并初始化值为5
cout << "原始链表:" << endl;
printList(head); // 打印原始链表
// 反转链表
ListNode* reversedHead = reverseList(head); // 调用反转函数
cout << "反转后的链表:" << endl;
printList(reversedHead); // 打印反转后的链表
return 0;
}
时间复杂度:O(n)
空间复杂度:O(1)
打卡




















