反转链表的三种方法
数据结构学习日记250902
迭代法反转链表
思路:逐一遍历,记录curr指针的前后位,将curr的next改为指向前节点,完成修改后更新curr为记录的后节点,实现curr的移动。
注意:curr在为空时停止遍历,此时的curr的前置节点才是新的头节点(因为链表已经反转)
/*
* 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) {
//排除头节点为空
if(head==nullptr){
return nullptr;
}
ListNode*pre=nullptr;
ListNode*curr=head;
while(curr){
//tmp为curr的后置节点
ListNode*tmp=curr->next;
curr->next=pre;
pre=curr;
curr=tmp;
}
//注意更新头节点
head=pre;
return head;
}
};
递归法反转
为什么可以使用递归??
我们将函数的参数设置为head->next;每递归一层,相当于向下遍历一个节点,在此过程中,前面节点的信息被存到了堆栈中!!便于后续回溯中利用上。
那么递归出口显然:head走到链表的最后一个节点,即head->next==nullptr。考虑到空链表可能会导致这里内存错误,因为head为空。完整的递归条件应该为:head==nullptr||head->next==nullptr。
两个注意点
1.完成链表反转后,怎么找到头节点?将原链表的尾节点一直作为返回值回传
2.首次触发return时,head是哪个节点?倒数第二个。此时已经回溯一层。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==nullptr||head->next==nullptr){
//第一次触发回溯的位置,空链表退出,或者是走到链表尾部退出
//这里返回的是链表的尾节点,尾节点需要一直保留,保证最后能正确给出反转后的链表头节点
return head;
}
ListNode*newHead=reverseList(head->next);
//head实际上是倒数第二个节点
head->next->next=head;
head->next=nullptr;
return newHead;
}
};
反转的核心逻辑
head->next->next=head;
head->next=nullptr;
这里以第一次回溯为例,将尾节点的next指向回溯得到的倒数第二个节点(head),将倒数第二个节点的后继置空!!没有这一步会导致原链表的头节点,也就是反转后链表的尾节点的next异常。
头插法反转链表
反转逻辑:将待反转区的前置节点prev保留,head记为待反转区的首个节点。
将head后的每个节点依次插入到prev的后方,即可实现链表的反转。
例题:leetcode92
为了保证当需要反转头节点时能够正确的反转,使用虚拟头节点dummy。与此同时反转后的链表的头节点也就变成了dummy->next。
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
// 采用头插法实现一次遍历
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* prev = dummy;
ListNode* curr = head;
// 走到需要反转的前一个节点
for (int i = 0; i < left - 1; ++i) {
prev=prev->next;
}
//此时的curr为待反转区域的首个节点
curr=prev->next;
//循环的次数为需要反转的链表节点个数
//每循环一次就可以将一个节点插入到prev的后方
for(int i=0;i<right-left;++i){
ListNode*nextNode=curr->next;
curr->next=nextNode->next;
nextNode->next=prev->next;
prev->next=nextNode;
}
return dummy->next;
}
};
浙公网安备 33010602011771号