「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」。
题目描述
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
示例1
输入: 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循环,将链表的元素都放入栈中,最后再输出栈中的元素,构建一个新链表返回。
或者为了只循环一次,不再使用栈存储元素,而是用递归的方式,不断输出当前链表反转后的头节点。