0 介绍
链表反转是一道常见的算法面试题,题意也很直白,就是让你将一个指定链表反序。Leetcode206题和92题考查了这样一道题目,下面来看一看。
1 Leetcode206题-反转链表I
该题题目描述如下:
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
解决这样一个问题需要三个指针pre、cur、tail,以示例输入为例,我们首先将pre初始化为空指针,cur初始化为输入链表的头指针。当cur不为空指针时,我们循环的将tail设置为cur的next指针,然后将cur的next指向pre,然后将pre指向cur,cur指向自己的next。循环结束之后,返回pre即可。下面结合代码体会一下这个过程。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr;
ListNode* cur = head;
while(cur != nullptr)//在确认cur不是空指针时为tail赋值
{
ListNode* tail = cur->next;
cur -> next = pre;
pre = cur;
cur = tail;
}
return pre;
}
};
2 Leetcode92题-反转链表II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
这道题是上一道的升级版,要求我们做一个局部反转,题目给好了待反转的区间。这道题我认为要关注4个位置,以示例输入为例,首先是起始反转的节点,在示例中便是2;第二个是起始反转节点的上一个节点,题目中为1;第三个是结束反转时的节点,题目中是4,最后一个是结束反转时的节点的下一个节点。我们操作pre和cur到达待反转的区域时,记录好上述四个节点,反转结束时将起始反转节点的上一个节点指向结束反转时的节点(1->4);将起始反转的节点指向结束反转时的节点的下一个节点(2->5)。
下面结合代码看一下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n)
{
ListNode* pre = nullptr,*cur = head;
ListNode *leftEnd,*rightEnd;
for(int i = 1; i < m; ++i)//cur到达开始反转的上一个节点
{
pre = cur;
cur = cur->next;
}
leftEnd = pre;//记录节点
pre = cur;
cur = cur->next;//cur到达待反转节点
rightEnd = pre;
for(int i = m; i < n; ++i)
{
ListNode* tail = cur->next;
cur -> next = pre;
pre = cur;
cur = tail;
}
//结束反转之后pre就是结束反转的节点的位置
if(leftEnd)
leftEnd->next = pre;
if(rightEnd)
rightEnd->next = cur;
if(m == 1)//如果m==1,对头节点进行了修改,返回pre
return pre;
return head;//其余情况返回head
}
};