【算法92】 反转链表ll

题目描述:(来源力扣92)

反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。

说明:
1 ≤ m ≤ n ≤ 链表长度。

示例:
在这里插入图片描述


先说一下,这道题自己做的过程,在这道题之前做了类似的反转链表(力扣206),那道题是反转整个链表,比较简单。这里就只贴出代码了:
力扣206:反转链表

class Solution {
public:
    ListNode* reverseList(ListNode* head) {

        ListNode* pre = nullptr;
        ListNode* cur = head;
        while (cur != nullptr){//反转整个链表
            ListNode* next = cur->next;

            cur->next=pre;
            pre=cur;
            cur=next;
        }
        return pre;
    }
};

反转局部链表的思路很简单,思路如下:

1)遍历链表,当遍历到m点位置,开始反转链表;
2)当遍历到n点位置,结束反转,并返回新的头结点;

但是实现的时候,就出现了很多不兼容的状况,比如:

1)m==n时,这时候不需要反转,直接返回就可以了;
2)m==1,即m是头结点;
3)链表为空;

尝试结果:
【算法92】 反转链表ll_第1张图片


具体分析: 【算法92】 反转链表ll_第2张图片

1)在到达m点之前,即m-1点,会使用left指针记录m点的前一个节点。如果,在反转结束我们需要将1点连接到4点。

【算法92】 反转链表ll_第3张图片

2)在到达m点,使用right指针记录反转部分链表的尾节点,这样最后才能找到2点和5点进行连接。

【算法92】 反转链表ll_第4张图片

具体实现:
class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(head== nullptr){
            return head;
        }

        ListNode* dummyhead= new ListNode(-1);//设立虚拟头结点
        dummyhead->next=head;
        ListNode* pre= dummyhead;
        ListNode* cur= head;
        int i=0;
        
        ListNode* left= nullptr;
        ListNode* right=nullptr;

        while (cur!=nullptr){
            if(i==m-1)
                left=pre;//记录left指针
            if(i==m)
                right=pre;//记录right指针

            while (i>=m&&i<n){//到达m点时,反转链表开始
                ListNode* next=cur->next;
                cur->next=pre;
                pre=cur;
                cur=next;
                ++i;
            }

            if(i==n){//到达n点,反转链表结束
                left->next=pre;
                right->next=cur;
                break;
            }
            //如果没有到达m点之前,即没有开始反转时
            //每次只向后遍历
            pre=cur;
            cur=cur->next;
            ++i;
        }
        return dummyhead->next;
    }
};
官方实现:

官方的实现更加体现了一次遍历的过程,清晰易懂:

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
        if(head== nullptr){
            return head;
        }


        ListNode* pre= nullptr;
        ListNode* cur= head;
        while (m>1){
            pre=cur;
            cur=cur->next;
            m--;
            n--;
        }
        ListNode* left=pre;
        ListNode* right=cur;
        ListNode* next= nullptr;

        while (n>0){
            next=cur->next;
            cur->next=pre;
            pre=cur;
            cur=next;
            n--;
        }

        if(left!=nullptr)
            left->next = pre;
        else
            head=pre;

        right->next=cur;

        return head;
    }
};

你可能感兴趣的:(leetcode,链表,反转)