总结单链表反转的三种常用方法
单链表反转是面试高频题目,非常基础必须掌握,这里记录C++实现的常用方法,以及Leetcode上可以用单链表反转解决的题目:判断链表是否回文。
链表结点
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
原链表直接进行迭代反转
用三个迭代指针prev,curr,next,分别记住当前结点,当前结点的原本的前继,和后继。
迭代过程:
1 next指针保存curr的后继
2 将当前结点curr的后继指向它原本的前继prev
3 将prev和curr指针向后迭代
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
ListNode* next;
while(curr!=nullptr)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};
通过stack中转
利用stack后进先出的特性,实现链表的反转,两遍遍历,第一遍将结点存储在stack中,第二遍弹出stack中保存的结点,重新链接。
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(head==NULL) return head;
stack<ListNode*> s;
s.push(NULL);
while(head!=NULL){
s.push(head);
head = head->next;
}
ListNode * curr = s.top();
head = s.top();
s.pop();
while(!s.empty()){
curr->next = s.top(); s.pop();
curr = curr->next;
}
return head;
}
};
递归实现反转
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL) {
return NULL;
}
if (head->next == NULL) {
return head;
}
ListNode* rest = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return rest;
}
};