数据结构与算法之链表: LeetCode 92. 反转链表 II (Ts版)

打印 上一主题 下一主题

主题 1011|帖子 1011|积分 3033

反转链表 II



  • https://leetcode.cn/problems/reverse-linked-list-ii/description/
形貌



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

   
  1. 输入:head = [1,2,3,4,5], left = 2, right = 4
  2. 输出:[1,4,3,2,5]
复制代码
示例 2

  1. 输入:head = [5], left = 1, right = 1
  2. 输出:[5]
复制代码
提示



  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n
  • 进阶: 你可以使用一趟扫描完成反转吗?
Typescript 版算法实现


1 ) 方案1: 穿针引线
  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. *     val: number
  5. *     next: ListNode | null
  6. *     constructor(val?: number, next?: ListNode | null) {
  7. *         this.val = (val===undefined ? 0 : val)
  8. *         this.next = (next===undefined ? null : next)
  9. *     }
  10. * }
  11. */
  12. const reverseLinkedList = (head: ListNode | null) => {
  13.     let pre = null;
  14.     let cur = head;
  15.     while (cur) {
  16.         const next = cur.next;
  17.         cur.next = pre;
  18.         pre = cur;
  19.         cur = next;
  20.     }
  21. }
  22. function reverseBetween(head: ListNode | null, left: number, right: number): ListNode | null {
  23.     // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
  24.     const dummyNode = new ListNode(-1);
  25.     dummyNode.next = head;
  26.     let pre = dummyNode;
  27.     // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
  28.     // 建议写在 for 循环里,语义清晰
  29.     for (let i = 0; i < left - 1; i++) {
  30.         pre = pre.next;
  31.     }
  32.     // 第 2 步:从 pre 再走 right - left + 1 步,来到 right 节点
  33.     let rightNode = pre;
  34.     for (let i = 0; i < right - left + 1; i++) {
  35.         rightNode = rightNode.next;
  36.     }
  37.     // 第 3 步:切断出一个子链表(截取链表)
  38.     let leftNode = pre.next;
  39.     let curr = rightNode.next;
  40.     // 注意:切断链接
  41.     pre.next = null;
  42.     rightNode.next = null;
  43.     // 第 4 步:同第 206 题,反转链表的子区间
  44.     reverseLinkedList(leftNode);
  45.     // 第 5 步:接回到原来的链表中
  46.     pre.next = rightNode;
  47.     leftNode.next = curr;
  48.     return dummyNode.next;
  49. };
复制代码
2 ) 方案2: 一次遍历「穿针引线」反转链表(头插法)
  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. *     val: number
  5. *     next: ListNode | null
  6. *     constructor(val?: number, next?: ListNode | null) {
  7. *         this.val = (val===undefined ? 0 : val)
  8. *         this.next = (next===undefined ? null : next)
  9. *     }
  10. * }
  11. */
  12. function reverseBetween(head: ListNode | null, left: number, right: number): ListNode | null {
  13.     // 设置 dummyNode 是这一类问题的一般做法
  14.     const dummy_node = new ListNode(-1);
  15.     dummy_node.next = head;
  16.     let pre = dummy_node;
  17.     for (let i = 0; i < left - 1; ++i) {
  18.         pre = pre.next;
  19.     }
  20.     let cur = pre.next;
  21.     for (let i = 0; i < right - left; ++i) {
  22.         const next = cur.next;
  23.         cur.next = next.next;
  24.         next.next = pre.next;
  25.         pre.next = next;
  26.     }
  27.     return dummy_node.next;
  28. };
复制代码
3 )方案3:局部反转法
  1. /**
  2. * Definition for singly-linked list.
  3. * class ListNode {
  4. *     val: number
  5. *     next: ListNode | null
  6. *     constructor(val?: number, next?: ListNode | null) {
  7. *         this.val = (val===undefined ? 0 : val)
  8. *         this.next = (next===undefined ? null : next)
  9. *     }
  10. * }
  11. */
  12. function reverseBetween(head: ListNode | null, left: number, right: number): ListNode | null {
  13.     const dummy = {
  14.         next: head
  15.     }
  16.     let tmp = dummy
  17.     for (let i = 0; i < left - 1; i++) {
  18.         tmp = tmp.next
  19.     }
  20.     let prev = tmp.next
  21.     let cur = prev.next
  22.     for (let j = 0; j < right - left; j++) {
  23.         let next = cur.next
  24.         cur.next = prev
  25.         prev = cur
  26.         cur = next // cur = cur.next
  27.     }
  28.     tmp.next.next = cur
  29.     tmp.next = prev
  30.     return dummy.next
  31. };
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

缠丝猫

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表