leetcode 92.反转链表 II

leetcode 92.反转链表 II_第1张图片
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii/

解题思路:

  • 截取并断开子链表
  • 对子链表进行遍历局部翻转
  • 将断开的部分进行重新连接成为一个新的链表
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    //这里进行子链表的整体反向链接
    void listReverse(ListNode* head){
        ListNode* pre = nullptr;
        ListNode* curr = head;
        ListNode* next = nullptr;
        //从头节点遍历到尾结点
        while(curr){
            next = curr->next;
            curr->next = pre;
            pre = curr;
            curr = next;
        }
    }
    ListNode *reverseBetween(ListNode *head, int left, int right) {
        // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
        ListNode *dummyNode = new ListNode(-1);
        dummyNode->next = head;

        ListNode *pre = dummyNode;
        // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
        // 建议写在 for 循环里,语义清晰
        for (int i = 0; i < left - 1; i++) {
            pre = pre->next;
        }

        // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
        ListNode *rightNode = pre;
        for (int i = 0; i < right - left + 1; i++) {
            rightNode = rightNode->next;
        }

        // 第 3 步:切断出一个子链表(截取链表)
        //curr 保存的是断开链表尾部的下一个结点,为了后面的连接提前存储
        ListNode *leftNode = pre->next;
        ListNode *curr = rightNode->next;

        // 注意:切断链接
        pre->next = nullptr;
        rightNode->next = nullptr;

        // 第 4 步:同第 206 题,反转链表的子区间
        listReverse(leftNode);

        // 第 5 步:接回到原来的链表中
        //rightNode是反转后的子链表的头节点,curr为断开前子链表尾结点的下一个结点
        pre->next = rightNode;
        leftNode->next = curr;
        return dummyNode->next;
    }

};

你可能感兴趣的:(刷题,数据结构与算法,单链表,链表)