反转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
辅助栈
通过栈辅助存取链表的值,然后遍历赋值。
时间复杂度O(n),空间复杂度O(n)。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *p = pHead;
stack<int> s;
while (p)
{
s.push(p->val);
p = p->next;
}
p = pHead;
while (p)
{
int t = s.top();
p->val = t;
s.pop();
p = p->next;
}
return pHead;
}
};
模拟反转
我们现在给出一种情况只有a、b结点,a.next = b, b.next = NULL。反转链表也就是要反转每个结点的next指向,我们来试着模拟这个过程。
如何使a -> b -> NULL 变成 NULL <- a <- b呢?
我们设立一个关系pre,head,next分别代表当前结点前一个结点指针,当前结点指针,当前结点后一个结点指针。
a -> b 这段关系对于a来说, pre = NULL, head = a, next = b。而反转之后,next = NULL, head = a, pre = b。
我们并不需要在a这个结点处同时修改它的pre和next指向关系,我们只需要修改pre就能使整个链表反转。
当head=a时,pre=NULL,next=b,我们将head->next = NULL,然后移向下一个节点。
当head=b时,pre=a,next=NULL,我们将head->next = a,然后移向下一个节点。
发现是NULL此时,我们已经完成了反转的工作,a->next = NULL, b ->next = a。
总结算法:
- 从head = pHead,pre = NULL,next = NULL开始循环修改直到head = NULL
- next = head->next,head->next = pre 修改当前结点head的指向
- 更新head和pre(也就是往后移动一个结点) pre = head, head = next
时间复杂度O(n),空间复杂度O(1)。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *pre = NULL, *next = NULL, *head = pHead;
while (head)
{
next = head->next;
head->next = pre;
pre = head;
head = next;
}
// 此时head = NULL,pre为链表的最后一个结点,也是反转链表的首结点
return pre;
}
};