1. 题目描述:
翻转一个链表,例如:给出一个链表1->2->3->null,这个翻转后的链表为3->2->1->null。
2. 链表数据结构
/**
* struct ListNode
* {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
**/
3. 代码
3.1 思路1:借助栈来实现
先扫描一遍链表保存每个节点的值,然后再从头到尾遍历,将栈中元素值一一赋给链表节点。时空复杂度都是O(n)。
class Solution
{
public:
ListNode *reverse(ListNode *head)
{
if(head == NULL)
{
return NULL;
}
stack<int> stk;
ListNode *cur = head;
while(cur != NULL)
{
stk.push(cur->val);
cur = cur->next;
}
cur = head;
while(cur != NULL)
{
cur->val = stk.top();
cur = cur->next;
stk.pop();
}
return head;
}
};
3.2 思路2:迭代
依次将从第二个结点到最后一个结点的后继设为头结点,然后将该节点设为头结点(需记住将原头结点的后继设为空)。
定义三个指针:p1,p2,p3,p1指向第1个结点;p2指向第2个结点,p3指向p2的下一个结点;然后将p1->next置为NULL(因为反转后,原先的第一个结点就是最后一个结点);接着将p2->next指向p1,p1和p2分别向后移动即可。
class Solution
{
public:
ListNode *reverse(ListNode *head)
{
if(head == NULL)
{
return NULL;
}
ListNode *p1 = head;
ListNode *p2 = head->next;
ListNode *p3;
p1->next = NULL;//反转后原来的第一个结点就是最后一个结点
while(p2 != NULL)
{
p3 = p2->next;
p2->next = p1; //p1,p2交替工作进行反向
p1 = p2;
p2 = p3;
}
head = p1; //反转后的第一个结点就是原来的最后一个结点
return head;
}
};
3.3 思路3:递归
首先反转从第二个结点到最后一个结点的链表,然后再将头结点放到已反转链表的最后,函数返回新链表的头结点。
class Solution
{
public:
ListNode* reverse(ListNode* head)
{
//此处的条件不能写成if(head == NULL)
if (head == NULL || head->next == NULL)
return head;
ListNode *newhead = reverse(head->next);
head->next->next = head;
head->next = NULL;
return newhead;
}
};