【题目描述】
输入一个链表,反转链表后,输出新链表的表头。
eg:
输入 | {1,2,3} |
---|---|
输出 | {3,2,1} |
【官方解法】
1.构造链表
此方法较为简单,思路是:先将链表中的元素赋给一个vector,在vector中用容器的反转函数reverse()实现反转操作,再将反转后的v给新建的链表并返回输出。
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
if (!pHead) return nullptr; //判空操作
vector<ListNode*> v; //创建vector
while (pHead) {
v.push_back(pHead); //将链表中的元素push进v中
//因为此处要push进去pHead,所以定义v的时候类型一定要是ListNode*
pHead = pHead->next;
}
reverse(v.begin(), v.end()); // 反转vector,也可以逆向遍历
ListNode *head = v[0];//构造新链表的头
ListNode *cur = head;
for (int i=1; i<v.size(); ++i) { // 构造链表
cur->next = v[i]; // 当前节点的下一个指针指向下一个节点
cur = cur->next; // 当前节点后移
}
cur->next = nullptr; // 切记最后一个节点的下一个指针指向nullptr
return head;
}
};
2.正规解法
官方说,面试的时候,上一种解法当然不行。
此题想考察的是:如何调整链表指针,来达到反转链表的目的。
初始化:3个指针
1)pre指针指向已经反转好的链表的最后一个节点,最开始没有反转,所以指向nullptr
2)cur指针指向待反转链表的第一个节点,最开始第一个节点待反转,所以指向head
3)nex指针指向待反转链表的第二个节点,目的是保存链表,因为cur改变指向后,后面的链表则失效了,所以需要保存
接下来,循环执行以下三个操作
1)nex = cur->next, 保存作用
2)cur->next = pre 未反转链表的第一个节点的下个指针指向已反转链表的最后一个节点
3)pre = cur, cur = nex; 指针后移,操作下一个未反转链表的第一个节点
循环条件,当然是cur != nullptr
循环结束后,cur当然为nullptr,所以返回pre,即为反转后的头结点
这里以1->2->3->4->5 举例:
class Solution {
public:
ListNode* ReverseList(ListNode* pHead) {
ListNode *pre = nullptr;
ListNode *cur = pHead;
ListNode *nex = nullptr; // 这里可以指向nullptr,循环里面要重新指向
while (cur) {
nex = cur->next;
cur->next = pre;
pre = cur;
cur = nex;
}
return pre;
}
};