力扣 反转链表(图解)

一:

供以后复习看看

206. 反转链表

难度简单

 

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

力扣 反转链表(图解)_第1张图片

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

力扣 反转链表(图解)_第2张图片

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

 

 图解:

 节点准备完成:力扣 反转链表(图解)_第3张图片  curr指向prev节点力扣 反转链表(图解)_第4张图片

移动prev节点:

力扣 反转链表(图解)_第5张图片 移动到curr位置:

力扣 反转链表(图解)_第6张图片

移动curr:

力扣 反转链表(图解)_第7张图片 

 

 力扣 反转链表(图解)_第8张图片

 此时第一个节点反转已完成

 随后就是next右移,curr再指向prev节点,然后向后移动两个节点,第二步完成。。。重复直到curr为空,返回prev即可

力扣 反转链表(图解)_第9张图片

 

代码:

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* prev = nullptr;//定义前节点和当前节点
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;//定义next节点,next是为了防止curr指向prev的时候,链表中断,无法获得后续节点
            curr->next = prev;//当前节点指向前节点,实现反转
            prev = curr;//prev节点后移一位
            curr = next;//curr节点向后移动一位
        }
        return prev;//循环结束,返回prev节点即可,不返回curr节点因为while循环退出时curr已经变为空节点了
    }
};

进阶:

92. 反转链表 II

难度中等1420收藏分享切换为英文接收动态反馈

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例 1:

力扣 反转链表(图解)_第10张图片

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

  这是力扣官方题解的图:力扣 反转链表(图解)_第11张图片

 

 简单来说就是先找到这个区间(left,right),但咱找的是left的前一个节点pre,看图即可看出原因,right就正常找就行,left,right找到之后,下步是把中间这个区间分离然后反转,分离就是让pre->next=nullptr,right->next=nullptr,然后反转这区间的链表,再连接

这是官方题解:

      

class Solution {
private:
    void reverseLinkedList(ListNode *head) {
        // 也可以使用递归反转一个链表
        ListNode *pre = nullptr;
        ListNode *cur = head;

        while (cur != nullptr) {
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
    }

public:
    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 步:切断出一个子链表(截取链表)
        ListNode *leftNode = pre->next;
        ListNode *curr = rightNode->next;

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

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

        // 第 5 步:接回到原来的链表中
        pre->next = rightNode;
        leftNode->next = curr;
        return dummyNode->next;
    }
};

作者:LeetCode-Solution
链接:https://leetcode.cn/problems/reverse-linked-list-ii/solution/fan-zhuan-lian-biao-ii-by-leetcode-solut-teyq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(leetcode,链表,数据结构,算法)