大致思路:
就是用头插法反转,只不过要对可能的情况多加考虑!
把链表分为三部分:前面不反转的before->h中间反转的->p后面不反转的。在遍历的过程中记录结点指针,最后进行连接。
实现之后发现有指向空指针什么的,发现是因为before初始化为NULL,但如果m==1,即从一开始就开始反转,就没有“前面不反转的部分”了,所以最后的before->next=h的连接就会出问题!!!所以,要考虑m==1的情况。同理,如果n==length of list呢?好像也可以,那样的话p是NULL,正好作为结尾。
题目规定了1<=m<=n<=length of list,这方面就不再考虑。
如果m==n,那么只反转一个结点,相当于没反转,直接返回head
最后,要注意返回,如果m==1,则返回反转链表的头h,若否,则返回head.
简单来说,就是要在写好程序之后多想想有没有一些特殊情况可以处理,可以从输入变量是否相等?是否为0或为1等一些特殊取值?来考虑!
AC代码:
/**
* 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) {
if(head==NULL)
return NULL;
if(head->next==NULL)
return head;
if(m==n) //如果m==n相当于翻转一个结点,没用
return head;
ListNode *p = head;
ListNode *before = head;
ListNode *m_p = NULL;
ListNode *h = NULL;
for(int i=0;i<m-1;i++)
{
if(i==m-2)
before=p;
p = p->next;
}
m_p = p; //用于之后连n+1
h = p; //用于头插
p = p->next;
for(int i=0;i<n-m;i++)
{
//头插
ListNode *a = p;
p = p->next;
a->next = h;
h = a;
}
if(m!=1) //因为如果是m==1要从一开始就反转,那就没有第m-1个结点了
before->next = h;
//将m_p与现在的p(第n+1个结点)相连 有可能这个p是NULL
m_p->next = p;
if(m==1)
return h;
else
return head; //这里要理解好。
}
};