IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【LeetCode 单链表专项】反转链表II(92) -> 正文阅读

[数据结构与算法]【LeetCode 单链表专项】反转链表II(92)

1. 题目

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

1.1 示例

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

img

  • 示例 2 2 2
    • 输入: head = [5]left = 1right = 1
    • 输出: [5]

1.2 说明

1.3 限制

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

1.4 进阶

你可以使用一趟扫描完成反转吗?

2. 解法一(穿针引线)

2.1 分析

  • 定位至需要进行节点反转的起始位置:
    需要注意的是,在通过迭代完成定位后,为了后续能够将反转的部分和未反转的部分连接起来(通过如下的最后一张图将知道此举的目的),需要记录此时整数 left 确定的节点及其左边相邻节点,这里分别用 left_nodeprev_node 来表示。
    在这里插入图片描述
  • 使用迭代的方式进行节点反转:
    • 进行第一次迭代:
      在这里插入图片描述
    • 进行第二次迭代:
      在这里插入图片描述
    • 进行第三次迭代:
      在这里插入图片描述
  • 将未反转部分和已反转部分进行连接:
    需要注意的是,在完成上述节点反转之后及连接之前,需要和一开始一样记录整数 right 确定的节点及其右边相邻的节点,分别用 right_nodesucc_node 来表示。
    在这里插入图片描述

2.2 解答

from sys import maxsize


class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    def append(self, val: int):
        node = ListNode(val)
        if self.head is None:
            self.head = node
            self.tail = node
        else:
            self.tail.next = node
            self.tail = self.tail.next


class Solution:
    def reverse_between(self, head: ListNode, left: int, right: int) -> ListNode:
        dummy = ListNode(maxsize)
        dummy.next = head
        predecessor, current = dummy, head
        for _ in range(left - 1):
            predecessor = current
            current = current.next
        prev_node, left_node = predecessor, current
        for _ in range(left - 1, right):
            successor = current.next
            current.next = predecessor
            predecessor = current
            current = successor
        right_node, succ_node = predecessor, current
        prev_node.next = right_node
        left_node.next = succ_node
        return dummy.next


def main():
    values = [1, 2, 3, 4, 5]
    linked_list = LinkedList()
    for value in values:
        linked_list.append(value)

    sln = Solution()
    reversed_head = sln.reverse_between(linked_list.head, 2, 4)

    cursor = reversed_head
    while cursor:
        print(cursor.val, end='\t')  # 1	4	3	2	5
        cursor = cursor.next


if __name__ == '__main__':
    main()

需要特别留意的是,这里使用了一个傀儡节点 dummy ,其 next 域指向 head 节点,这样做避免了讨论当待反转节点包括头节点的情况。

2.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

3. 解法二(头插法)

3.1 解答

from sys import maxsize


class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next


class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    def append(self, val: int):
        node = ListNode(val)
        if self.head is None:
            self.head = node
            self.tail = node
        else:
            self.tail.next = node
            self.tail = self.tail.next


class Solution:
    def reverse_between(self, head: ListNode, left: int, right: int) -> ListNode:
        dummy = ListNode(maxsize)
        dummy.next = head
        predecessor, current = dummy, head
        for _ in range(left - 1):
            predecessor = current
            current = current.next
        for _ in range(left, right):
            successor = current.next
            current.next = successor.next
            successor.next = predecessor.next
            predecessor.next = successor
        return dummy.next


def main():
    values = [1, 2, 3, 4, 5]
    linked_list = LinkedList()
    for value in values:
        linked_list.append(value)

    sln = Solution()
    reversed_head = sln.reverse_between(linked_list.head, 2, 4)

    cursor = reversed_head
    while cursor:
        print(cursor.val, end='\t')  # 1	4	3	2	5
        cursor = cursor.next


if __name__ == '__main__':
    main()

3.2 分析

3.3 复杂度

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-12-23 15:58:58  更:2021-12-23 15:59:08 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 16:40:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码