力扣第92题——反转链表 II(C语言题解)

这篇具有很好参考价值的文章主要介绍了力扣第92题——反转链表 II(C语言题解)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目描述

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

示例 1:

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

输入: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

方法一:穿针引线

我们以下图中黄色区域的链表反转为例。力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

使用「206. 反转链表」的解法,反转 left 到 right 部分以后,再拼接起来。我们还需要记录 left 的前一个节点,和 right 的后一个节点。如图所示:力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

算法步骤:

第 1 步:先将待反转的区域反转;
第 2 步:把 pre 的 next 指针指向反转以后的链表头节点,把反转以后的链表的尾节点的 next 指针指向 succ。力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

说明:编码细节我们不在题解中介绍了,请见下方代码。思路想明白以后,编码不是一件很难的事情。这里要提醒大家的是,链接什么时候切断,什么时候补上去,先后顺序一定要想清楚,如果想不清楚可以在纸上模拟.

void reverseLinkedList(struct ListNode *head) {
    // 也可以使用递归反转一个链表
    struct ListNode *pre = NULL;
    struct ListNode *cur = head;

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

struct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    struct ListNode *dummyNode = malloc(sizeof(struct ListNode));
    dummyNode->val = -1;
    dummyNode->next = head;

    struct 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 节点
    struct ListNode *rightNode = pre;
    for (int i = 0; i < right - left + 1; i++) {
        rightNode = rightNode->next;
    }

    // 第 3 步:切断出一个子链表(截取链表)
    struct ListNode *leftNode = pre->next;
    struct ListNode *curr = rightNode->next;

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

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

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

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言 

方法二:一次遍历「穿针引线」反转链表(头插法)

方法一的缺点是:如果 left 和 right 的区域很大,恰好是链表的头节点和尾节点时,找到 left 和 right 需要遍历一次,反转它们之间的链表还需要遍历一次,虽然总的时间复杂度为 O(N)O(N)O(N),但遍历了链表 222 次,可不可以只遍历一次呢?答案是可以的。我们依然画图进行说明。

我们依然以方法一的示例为例进行说明。力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

整体思想是:在需要反转的区间里,每遍历到一个节点,让这个新节点来到反转部分的起始位置。下面的图展示了整个流程。

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

下面我们具体解释如何实现。使用三个指针变量 pre、curr、next 来记录反转的过程中需要的变量,它们的意义如下:

curr:指向待反转区域的第一个节点 left;
next:永远指向 curr 的下一个节点,循环过程中,curr 变化以后 next 会变化;
pre:永远指向待反转区域的第一个节点 left 的前一个节点,在循环过程中不变。
第 1 步,我们使用 ①、②、③ 标注「穿针引线」的步骤。

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

操作步骤:

先将 curr 的下一个节点记录为 next;
执行操作 ①:把 curr 的下一个节点指向 next 的下一个节点;
执行操作 ②:把 next 的下一个节点指向 pre 的下一个节点;
执行操作 ③:把 pre 的下一个节点指向 next。
第 1 步完成以后「拉直」的效果如下:

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

第 2 步,同理。同样需要注意 「穿针引线」操作的先后顺序。

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

第 2 步完成以后「拉直」的效果如下:

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

第 3 步,同理。

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

第 3 步完成以后「拉直」的效果如下:力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言

struct ListNode *reverseBetween(struct ListNode *head, int left, int right) {
    // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
    struct ListNode *dummyNode = malloc(sizeof(struct ListNode));
    dummyNode->val = -1;
    dummyNode->next = head;

    struct ListNode *pre = dummyNode;
    for (int i = 0; i < left - 1; i++) {
        pre = pre->next;
    }
    struct ListNode *cur = pre->next;
    struct ListNode *next;
    for (int i = 0; i < right - left; i++) {
        next = cur->next;
        cur->next = next->next;
        next->next = pre->next;
        pre->next = next;
    }
    return dummyNode->next;
}

力扣第92题——反转链表 II(C语言题解),leetcode,链表,c语言文章来源地址https://www.toymoban.com/news/detail-817306.html

到了这里,关于力扣第92题——反转链表 II(C语言题解)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「双指针」删除排序链表中的重复元素 II(力扣第82题)

    本题为1月15日力扣每日一题 题目来源:力扣第82题 题目tag: 链表 双指针 给定一个已排序的链表的头head,删除原始链表中所有重复数字的节点,只留下不同的数字。返回已排序的链表。 示例 1 输入: 输出: 示例 2 输入: 输出: 链表中节点数目在范围$ [0,300] $内 $ -100 leq Nod

    2024年02月01日
    浏览(41)
  • LeetCode 92. Reverse Linked List II【链表,头插法】中等

    本文属于「征服LeetCode」系列文章之一,这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁,本系列将至少持续到刷完所有无锁题之日为止;由于LeetCode还在不断地创建新题,本系列的终止日期可能是永远。在这一系列刷题文章中,我不仅会讲解多种解题思路及其优化,

    2024年02月09日
    浏览(31)
  • 力扣第236题——二叉树的最近公共祖先 (C语言题解)

    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大( 一个节点也可以是它自己的祖先 )。” 示例 1: 示例 2: 示例

    2024年01月20日
    浏览(31)
  • 【LeetCode力扣】234 快慢指针 | 反转链表 | 还原链表

      目录 1、题目介绍 2、解题思路 2.1、暴力破解法 2.2、快慢指针反转链表   原题链接:  234. 回文链表 - 力扣(LeetCode) 示例 1: 输入: head = [1,2,2,1] 输出: true  示例 2: 输入: head = [1,2] 输出: false  提示:  链表中节点数目在范围[1, 10^5] 内 0 = Node.val = 9 进阶: 你能否用

    2024年02月08日
    浏览(31)
  • 【力扣 445】两数相加 II C++题解(链表+模拟+数学+头插法)

    给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。 你可以假设除了数字 0 之外,这两个数字都不会以零开头。 示例1: 输入:l1 = [7,2,4,3], l2 = [5,6,4] 输出:[7,8,0,7] 示例2: 输入:l

    2024年01月24日
    浏览(30)
  • 力扣每日一道系列 --- LeetCode 206. 反转链表

    📷 江池俊: 个人主页 🔥个人专栏: ✅数据结构探索 ✅LeetCode每日一道 🌅 有航道的人,再渺小也不会迷途。 LeetCode 206. 反转链表 初始化两个指针, cur 和 newhead 。 cur 指向给定的链表头节点, newhead 初始为 NULL 。 在 cur 不为空的情况下,执行循环。 首先,记录下 cur 的下

    2024年02月04日
    浏览(31)
  • 【C++】每日一题 92 反转链表

    给你单链表的头指针 head 和两个整数 left 和 right ,其中 left = right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。 先创建一个虚拟头节点 dummy,然后找到需要反转位置的前一个节点 pre。接着进行反转操作,将节点逐个插入到 pre 节点之后,最后返回虚拟

    2024年03月11日
    浏览(30)
  • LeetCode - 142. 环形链表 II (C语言,快慢指针,配图)

            如果你对快慢指针,环形链表有疑问,可以参考下面这篇文章,了解什么是环形链表后,再做这道题会非常简单,也更容易理解下面的图片公式等。 LeetCode - 141. 环形链表 (C语言,快慢指针,配图)-CSDN博客         上述文章总结: 如果一个链表是环形链表,采用

    2024年02月05日
    浏览(39)
  • C语言 | Leetcode C语言题解之第21题合并两个有序链表

    题目: 题解:

    2024年04月12日
    浏览(30)
  • 力扣541.反转字符串II

    原题链接:力扣541.反转字符串II 思路: 其实在遍历字符串的过程中,只要让 i += (2 * k),i 每次移动 2 * k 就可以了,然后判断是否需要有反转的区间。 因为要找的也就是每2 * k 区间的起点,这样写,程序会高效很多。 全代码:

    2024年02月06日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包