人生第一个算法题——206. 反转链表

200 阅读2分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。

题目描述

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

示例1 image.png

输入: head = [1,2,3,4,5]
输出: [5,4,3,2,1]

思路分析

这道题应该是企业面试出得概率最高的一个了,算是一个算法的门槛,不是贪心动态规划dfs等具有模版的题,需要用脑子想想。

链表最基础的一步应该是插入节点

 q->next = p->next;
 p->next = q;

那么,我们看将链表反转这件事,实际上就是不断地将tmp后面的节点,插入到tmp前面来

ListNode* p = tmp->next;
tmp -> next= p->next;
p ->next = tmp;
//这步其实不算是这部分逻辑,只是写到循环里要用
tmp = p;

如上,先找到tmp后面的节点p,在将tmp->next指向p后面的节点,最后将p插到tmp前面。

然而这种方式只是易于理解,或者说将反转变成了插入。我们在熟悉这种思想后也可以试着直接反转。

具体实现

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* tmp = head;
        ListNode* node = nullptr;
        while(tmp != nullptr) {
            ListNode* ptr = tmp->next;
            tmp->next = node;
            node = tmp;
            tmp = ptr;
        }
        return node;
        
    }
};

总结

反转链表说起来应该也是我写算法的第一题。但当时学长给我讲的时候还并不能理解这个算法,只是背了背代码(毕竟没几行),后来果然忘了,因此做题还是要理解为上。

说到反转本身,其实也可以理解为一种后入先出,也就是栈。

我们可以遍历一次for循环,将链表的元素都放入栈中,最后再输出栈中的元素,构建一个新链表返回。

或者为了只循环一次,不再使用栈存储元素,而是用递归的方式,不断输出当前链表反转后的头节点。