Reverse a linked list from position m to n. Do it in-place and in one-pass.
For example:
Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.
Note:
Given m, n satisfy the following condition:
1 ≤ m ≤ n ≤ length of list.
大意是翻转部分或者全部代码:
我刚开始写的很乱,因为考虑很多边界问题,出了很多错,首先是如果m=n=1,也就是说m和n一样的情况。然后是m=1的情况,m=1就意味着没有前一个节点,需要分两种情况考虑。
总结一下我的思路:
1,首先找到要反转的那部分节点,我是通过num叠加找到的,记录这部分节点前一个节点pre,将这部分节点开始节点记为p,记录这部分节点后一个节点q。
2,将p和q输入到reverse函数,也就是倒转函数,利用3节点法。
3,融合链表,分情况考虑,第一,pre == NULL的情况,这时直接将head = reverse返回节点;第二,pre !=NULL,那么pre->next = reverse返回节点。
这道题的难点在于边界情况很难想清楚,有点打脑袋。
代码如下:
/**
* 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) {
int num = 1;
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* p;
ListNode* q;
if(head == NULL && head->next == NULL)
{
return head;
}
while(num != m)
{
pre = cur;
cur = cur->next;
num++;
}
p = cur;
while(num != n)
{
cur = cur->next;
num++;
}
cur = cur->next;
q = cur; //将q设置为下一个节点有好处,在反转时可以节约很多运算时间
if(pre == NULL)
{
head = reverse(p , q);
p->next = cur;
}
else
{
pre->next = reverse(p , q);
p->next = cur;
}
return head;
}
ListNode* reverse(ListNode* head,ListNode* q) //翻转的思想很简单,就是3节点翻转思想,cur指向pre ,pre= cur,cur = next。另外不改变head有好处。
{
ListNode* pre = NULL;
ListNode* cur = head;
ListNode* next ;
while(cur != q)
{
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
return pre;
}
};