螺旋矩阵 II:从理论到实践的五种算法解析

简介: 螺旋矩阵 II:从理论到实践的五种算法解析

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。

会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区:码上找工作

作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

python数据分析可视化:企业实战案例

备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

题目描述

给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。

输入格式
  • head:链表的头节点。
  • k:一个整数,表示旋转的位置数。
输出格式
  • 返回旋转后的链表的头节点。

示例

示例 1
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NULL

方法一:闭合为环

解题步骤
  1. 链表长度:首先遍历整个链表得到链表长度 n 和最后一个节点。
  2. 闭合成环:将链表的尾节点连接到头节点,形成环。
  3. 计算新头位置:根据 k % n 计算新的头节点的位置。
  4. 重置头节点:找到新的头节点和尾节点,断开环。
完整的规范代码
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
def rotateRight(head, k):
    """
    使用闭合环的方法进行链表旋转
    :param head: ListNode, 链表的头节点
    :param k: int, 旋转的位置数
    :return: ListNode, 旋转后的链表头节点
    """
    if not head or not head.next or k == 0:
        return head
    
    # 计算链表长度并形成环
    lastElement = head
    length = 1
    while lastElement.next:
        lastElement = lastElement.next
        length += 1
    lastElement.next = head
    
    # 找到新的尾部:(长度 - k % 长度 - 1)的位置
    k = k % length
    steps_to_new_tail = length - k
    new_tail = head
    for i in range(steps_to_new_tail - 1):
        new_tail = new_tail.next
    
    new_head = new_tail.next
    
    # 断开环
    new_tail.next = None
    
    return new_head
# 示例代码用于创建链表和打印链表
def create_list(lst):
    head = current = ListNode(lst[0])
    for number in lst[1:]:
        current.next = ListNode(number)
        current = current.next
    return head
def print_list(node):
    while node:
        print(node.val, end=" -> ")
        node = node.next
    print("NULL")
# 示例调用
lst = create_list([1, 2, 3, 4, 5])
rotated_lst = rotateRight(lst, 2)
print_list(rotated_lst)  # 输出: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
算法分析
  • 时间复杂度:(O(n)),主要时间开销来自于链表遍历和旋转计算。
  • 空间复杂度:(O(1)),除了给定的链表结构,只使用常数额外空间。

方法二:数组模拟

解题步骤
  1. 转换为数组:遍历链表,存储每个节点的值到数组中。
  2. 数组旋转:对数组进行旋转操作。
  3. 重建链表:根据旋转后的数组重建链表。
完整的规范代码
def rotateRight(head, k):
    """
    使用数组模拟链表旋转
    :param head: ListNode, 链表的头节点
    :param k: int, 旋转的位置数
    :return: ListNode, 旋转后的链表头节点
    """
    if not head or not head.next or k == 0:
        return head
    
    # 转换链表到数组
    nodes = []
    current = head
    while current:
        nodes.append(current.val)
        current = current.next
    
    # 数组旋转
    k = k % len(nodes)
    nodes = nodes[-k:] + nodes[:-k]
    
    # 重建链表
    new_head = current = ListNode(nodes[0])
    for val in nodes[1:]:
        current.next = ListNode(val)
        current = current.next
    
    return new_head
# 示例调用
lst = create_list([1, 2, 3, 4, 5])
rotated_lst = rotateRight(lst, 2)
print_list(rotated_lst)  # 输出: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
算法分析
  • 时间复杂度:(O(n)),包括链表到数组的转换和数组的旋转。
  • 空间复杂度:(O(n)),需要额外空间来存储链表元素的数组。

方法三:直接旋转

解题步骤
  1. 链表遍历:计算链表长度并连接成环。
  2. 计算新尾部:根据旋转次数确定新的尾部位置。
  3. 重建链表:在新的尾部断开环,形成新的链表。
完整的规范代码
def rotateRight(head, k):
    """
    直接通过链表旋转实现
    :param head: ListNode, 链表的头节点
    :param k: int, 旋转的位置数
    :return: ListNode, 旋转后的链表头节点
    """
    if not head or not head.next or k == 0:
        return head
    
    # 计算长度并形成环
    old_tail = head
    length = 1
    while old_tail.next:
        old_tail = old_tail.next
        length += 1
    old_tail.next = head
    
    # 计算新尾部位置
    k = k % length
    new_tail = head
    for i in range(length - k - 1):
        new_tail = new_tail.next
    
    new_head = new_tail.next
    new_tail.next = None
    
    return new_head
# 示例调用
lst = create_list([1, 2, 3, 4, 5])
rotated_lst = rotateRight(lst, 2)
print_list(rotated_lst)  # 输出: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
算法分析
  • 时间复杂度:(O(n)),需要遍历链表两次。
  • 空间复杂度:(O(1)),仅使用常数额外空间。

方法四:改进的数组模拟

解题步骤
  1. 转换为数组:将链表节点转换为数组,方便随机访问。
  2. 数组旋转:对数组进行旋转操作。
  3. 重建链表:根据旋转后的数组重建链表。
完整的规范代码
def rotateRight(head, k):
    """
    使用改进的数组模拟方法旋转链表
    :param head: ListNode, 链表的头节点
    :param k: int, 旋转的位置数
    :return: ListNode, 旋转后的链表头节点
    """
    if not head:
        return None
    
    # 转换链表到数组
    nodes = []
    while head:
        nodes.append(head)
        head = head.next
    
    k = k % len(nodes)
    nodes = nodes[-k:] + nodes[:-k]
    
    # 重建链表
    for i in range(len(nodes) - 1):
        nodes[i].next = nodes[i + 1]
    nodes[-1].next = None
    
    return nodes[0]
# 示例调用
lst = create_list([1, 2, 3, 4, 5])
rotated_lst = rotateRight(lst, 2)
print_list(rotated_lst)  # 输出: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
算法分析
  • 时间复杂度:(O(n)),链表到数组的转换和数组旋转各需要 (O(n))。
  • 空间复杂度:(O(n)),需要额外空间来存储节点指针的数组。

方法五:反向索引旋转

解题步骤
  1. 链表遍历:一次遍历计算链表长度并形成尾部连接。
  2. 反向计算头部:使用长度减去 (k % \text{长度}) 计算新头部和尾部位置。
  3. 断开连接:在新尾部断开链表,形成新的链表结构。
完整的规范代码
def rotateRight(head, k):
    """
    使用反向索引旋转链表
    :param head: ListNode, 链表的头节点
    :param k: int, 旋转的位置数
    :return: ListNode, 旋转后的链表头节点
    """
    if not head or not head.next or k == 0:
        return head
    
    # 完成一次完整遍历以确定长度并形成环
    last = head
    length = 1
    while last.next:
        last = last.next
        length += 1
    last.next = head
    
    # 确定新的头部和尾部
    k = k % length
    if k:
        for _ in range(length - k):
            last = last.next
    head = last.next
    last.next = None
    
    return head
# 示例调用
lst = create_list([1, 2, 3, 4, 5])
rotated_lst = rotateRight(lst, 2)
print_list(rotated_lst)  # 输出: 4 -> 5 -> 1 -> 2 -> 3 -> NULL
算法分析
  • 时间复杂度:(O(n)),可能需要遍历链表两次(计算长度和调整位置)。
  • 空间复杂度:(O(1)),不需要额外的存储空间,除了输入的链表。

不同算法的优劣势对比

特征 方法一: 闭环 方法二: 数组模拟 方法三: 直接旋转 方法四: 改进数组模拟 方法五: 反向索引旋转
时间复杂度 (O(n)) (O(n)) (O(n)) (O(n)) (O(n))
空间复杂度 (O(1)) (O(n)) (O(1)) (O(n)) (O(1))
优势 直观简单,实现快速 方便理解和实现,便于调试 减少了中间转换步骤,提高效率 易于理解和操作,灵活处理 计算头尾连接,避免额外空间,快速
劣势 需要特别处理新的头尾 需要额外空间存储数组,增加空间复杂度 需要准确计算长度和剩余部分 需要额外空间且稍复杂 需要两次遍历,稍增时间开销

应用示例

游戏开发中的角色队列管理

在多人在线游戏中,经常需要管理玩家的队列,例如在战场游戏中旋转玩家的出场顺序。使用旋转链表的算法可以有效地管理这种动态变化的玩家队列,确保每个玩家都能公平地参与游戏,同时也支持快速的动态调整。

欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
10天前
|
机器学习/深度学习 搜索推荐 算法
推荐系统的算法与实现:深入解析与实践
【6月更文挑战第14天】本文深入探讨了推荐系统的原理与实现,包括用户和项目建模、协同过滤、内容过滤及混合推荐算法。通过收集用户行为数据,系统预测用户兴趣,提供个性化推荐。实践中,涉及数据处理、建模、算法选择及结果优化。随着技术发展,推荐系统将持续改进,提升性能和用户体验。
|
12天前
|
算法 量子技术 数据库
量子计算:从理论到实践的深度解析
在当前科技迅猛发展的时代,量子计算作为一项颠覆性的技术正在不断引起广泛关注。本文旨在深入探讨量子计算的理论基础、关键技术和实际应用,并分析其未来发展前景及面临的挑战。通过对量子比特、纠缠态和量子门操作等核心概念的详细阐述,读者将能够全面理解量子计算的基本原理和潜在影响。
19 0
|
1天前
|
安全 生物认证 区块链
智能家居安全:从理论到实践的全面解析
【6月更文挑战第22天】本文深入探讨了智能家居安全领域的核心问题,旨在为读者提供一套完整的安全解决方案。文章首先界定了智能家居安全的重要性和面临的挑战,随后详细分析了常见的安全威胁类型,并提出了相应的防御策略。通过案例分析,本文展示了如何将理论知识应用于实际中,以增强智能家居系统的安全性。最后,文章对智能家居安全的未来趋势进行了预测,并强调了持续研究的必要性。
|
21小时前
|
机器学习/深度学习 算法 数据挖掘
算法金 | K-均值、层次、DBSCAN聚类方法解析
**摘要:** 这篇文章介绍了聚类分析的基本概念和几种主要的聚类算法。聚类是无监督学习中用于发现数据内在结构的技术,常用于市场分析、图像分割等场景。K-均值是一种基于划分的算法,简单高效但易受初始值影响;层次聚类包括凝聚和分裂方式,形成层次结构但计算复杂;DBSCAN基于密度,能处理任意形状的簇,但参数选择敏感。文章还讨论了这些算法的优缺点和适用场景,并提供了相关资源链接和Python实现。
19 9
算法金 | K-均值、层次、DBSCAN聚类方法解析
|
3天前
|
存储 弹性计算 安全
构建高效企业应用架构:阿里云产品组合实践深度解析
该方案展现了阿里云产品组合的强大能力和灵活性,不仅满足了当前业务需求,也为未来的扩展打下了坚实的基础。希望本文的分享能为读者在设计自己的IT解决方案时提供一定的参考和启发。
20 1
|
6天前
|
机器学习/深度学习 算法 TensorFlow
Inception v3算法的实战与解析
Inception v3算法的实战与解析
|
10天前
|
存储 前端开发 Java
深入解析Java类加载机制:原理、过程与实践
深入解析Java类加载机制:原理、过程与实践
15 2
|
13天前
|
监控 Cloud Native 持续交付
云原生架构:从理念到实践的全面解析
云原生架构已经成为现代软件开发和部署的核心理念。它不仅改变了传统的软件开发模式,还为企业提供了更高的灵活性、可扩展性和可靠性。本篇文章将深入探讨云原生架构的基本概念、关键组件以及实际应用案例,帮助读者更好地理解和应用这一先进的技术框架。
77 3
|
4天前
|
存储 算法 Java
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
面试高频算法题汇总「图文解析 + 教学视频 + 范例代码」之 二分 + 哈希表 + 堆 + 优先队列 合集
9 0
|
5天前
|
机器学习/深度学习 算法 数据可视化
决策树算法:从原理到实践的深度解析
决策树算法:从原理到实践的深度解析
10 0

推荐镜像

更多