Leetcode 92. 反转链表 II

题目传送门

解题思路:

  首先,题目要求我们将一个单链表的特定区间内的节点反转,这个区间是不确定的(对于单链表的反转来说,可以先用206. 反转链表来练练手).
  本题是没有空的头节点的,由于可能会涉及到头节点的操作,我们可以创建一个虚拟的节点来充当头节点,这样可以减少一些特殊情况,让我们的解法可以适用到更多的范围。然后我们来看一下反转的具体操作是什么。image
  我们反转的区间就是两个红色箭头的内部。我们看一下内部该怎么反转,我们需要将区间内部的节点的\(next\)都指向它的前一个节点,从图上看就是这样
image
因此我们就需要记录当前节点和其下一个节点。分别用\(cur\)\(curNext\)来表示。然后每次反转之后,我们要将\(cur\)\(curNext\)都向后移动到下一个节点,对于\(cur\)来说就是移动到\(curNext\),而\(curNext\)就是移动到其下一个节点,也就是\(curNext->next\)
  由于是区间内的反转,从图上也可以看出,我们还有节点没有连接上以及指针没有正确的指向,所以最后我们需要将开始反转节点的前一个节点\(pre\)\(next\)指向我们反转后链表的头节点,将反转后链表的尾节点指向剩下没有被反转的区间。最后反转的效果就是这样:image

代码:

code
/**
 * 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:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        if(left==right) return head;//特殊情况,也可以不用写
        ListNode *dummy=new ListNode(0);
        dummy->next=head;//创建虚拟头节点并连接
        ListNode *pre=dummy;
        for(int i=0;i<left-1;i++) pre=pre->next;
        ListNode *cur=pre->next,*curNext=cur->next;
        for(int i=0;i<right-left;i++)
        {
            ListNode *next=curNext->next;//记录下curNext下一步要移动到的位置
            curNext->next=cur;
            cur=curNext;//这里的顺序不能错,两个节点往后跳
            curNext=next;
        }
        pre->next->next=curNext;//将链表连接起来
        pre->next=cur;
        return dummy->next;
    }
};
posted @ 2021-03-25 23:39  Daneii  阅读(19)  评论(0编辑  收藏  举报