【链表】反转链表II:只反转一部分结点

大致思路:

就是用头插法反转,只不过要对可能的情况多加考虑!

把链表分为三部分:前面不反转的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; //这里要理解好。
    }
};

猜你喜欢

转载自blog.csdn.net/m0_38033475/article/details/92396783