Leetcode 206. 反转链表

311 阅读2分钟

原题链接: 206. 反转链表 - 力扣(Leetcode)

tag: 链表.

一. 题目

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

二. 题解

本题采用三指针的解法, 前指针 prev , 中指针 curr , 后指针 temp .

反转前.

image.png

ListNode* prev = nullptr, * curr = head;

image.png

开始进行反转操作.

image.png

定义一个 temp 指针指向 curr 节点的后继节点.

ListNode* temp = curr->next;

image.png

为什么要保存 curr 节点的后继节点呢? 因为接下来会进行反转操作, 也就是改变 curr->next 的指向, 将 curr->next 指向 prev 节点, 如果不用 temp 指针保存 curr 节点的后继节点, 就再也找不到 curr 节点原来的后继节点了, 无法继续对链表进行反转操作, 所以我们需要用 temp 指针保存 curr 节点的后继节点.

进行反转操作(改变 curr->next 的指向).

curr->next = prev;

image.png

更新 prev 指针.

prev = curr;

image.png

更新 curr 指针.

curr = temp;

image.png

继续反转链表.

image.png

定义一个 temp 指针指向 curr 节点的后继节点.

ListNode* temp = curr->next;

image.png

进行反转操作(改变 curr->next 的指向).

curr->next = prev;

image.png

更新 prev 指针.

prev = curr;

image.png

更新 curr 指针.

curr = temp;

image.png

curr == nullptr, 遍历链表完毕, 循环终止, 此时 prev 正好指向反转后链表的头节点.

image.png

反转后.

image.png

三. 复杂度分析

时间复杂度: O(N), N 是链表的长度, 完成链表的反转需要遍历链表一次.

空间复杂度: O(1).

四. 代码

/**
 * 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) {
        ListNode* prev = nullptr, * curr = head;    // 定义前指针 prev, 中指针 curr
        while (curr != nullptr) {
            ListNode* temp = curr->next;    // 保存 curr 的后继节点
            curr->next = prev;    // 进行反转操作
            prev = curr;    // 更新 prev 指针
            curr = temp;    // 更新 curr 指针
        }
        return prev;    // 返回新的头节点
    }
};