每日一算法题-翻转链表

63 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

一、题目

image.png

struct ListNode {
    int val;
    ListNode *next = nullptr;
    inline ListNode(int x, ListNode* next = nullptr) : val(x), next(next) { }
};
ListNode* reverseList(ListNode* pHead) {
    ListNode* result = nullptr;
    //------
    return result;
}

int main()
{
    ListNode root(1);
    ListNode p2(2);
    ListNode p3(3);
    root.next = &p2;
    p2.next = &p3;
    p3.next = nullptr;

    ListNode* pHead = &root;
    ListNode* cur = pHead;
    while(cur){
        cout << cur->val << endl;
        cur = cur->next;
    }
    cur = reverseList(pHead);
    while(cur){
        cout << cur->val << endl;
        cur = cur->next;
    }

    return 0;
}

二、分析

ListNode *next = nullptr;

难点一: 该链表是单向链表
难点二: 要返回新的表头

根据题意,我们需要将链表反转,说到链表,很容易想到只需要获取下一个节点,让下一个节点的next指针指向自己,再让下一个节点的下一个节点的next指针指向下一个节点,循环下去就能达到目的。

但是这样就造成了修改了p2的next,就无法获取p3的指针了

将算法修改一下,先获取p3,再去修改p2,就能达到目的了。

三、模拟

  1. 获取当前节点

ListNode* cur = pHead;

  1. 获取下一个节点

ListNode* next = cur->next;

  1. 修改当前节点

cur->next = cur->(之前指向cur的节点);

  1. 迭代

cur = next;

如此循环修改便能完成,模拟过程中只有一个未知量,就是指向当前节点的前节点,设为pre,头指针是第一个节点,在转变后,就是最后一个节点,最后一个节点的next应该等于NULL,然后在循环迭代过程中,pre一直等于修改的当前节点。

四、实现

ListNode* reverseList(ListNode* pHead) {
    ListNode* result = nullptr;
    ListNode* cur = pHead;
    ListNode* pre = nullptr;
    while(cur){
        ListNode* next = cur->next;
        cur->next = pre;
        pre = cur;
        cur = next;
    }
    result = pre;
    return result;
}

因为循环的原因,cur指向NULL才结束循环,而真正的头结点就是NULL之前的节点,也就是pre

五、结言

这道题有两个思维误区:

1. 倒转需要先修改前面的节点
2. 当前结点倒转后就是之前next节点的next指针