【LeetCode刷题】轮转数组

给定一个整数数组 nums,将数组中的元素向右轮转 k个位置,其中 k是非负数。

示例 1:

复制代码
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

复制代码
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

  • 1 <= nums.length <=
  • -231 <= nums[i] <=
  • 0 <= k <=

解题思路

  1. 处理有效轮转步数 :由于k可能大于数组长度,先对k取模(k = k % len(nums)),确保k是有效步数。
  2. 三次翻转数组
    • 翻转整个数组
    • 翻转前 k 个元素
    • 翻转剩余元素

Python代码:

python 复制代码
from typing import List


class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        轮转数组:三次翻转法,原地修改,时间O(n),空间O(1)
        """
        n = len(nums)
        if n == 0:  # 处理空数组边界情况
            return
        k %= n  # 处理k超过数组长度的情况,取有效轮转步数

        # 定义内部翻转函数(双指针法,原地修改数组)
        def reverse(lst: List[int], start: int, end: int) -> None:
            while start < end:
                # 交换首尾元素,向中间逼近
                lst[start], lst[end] = lst[end], lst[start]
                start += 1
                end -= 1

        # 核心:三次翻转实现轮转
        reverse(nums, 0, n - 1)  # 第一步:翻转整个数组
        reverse(nums, 0, k - 1)  # 第二步:翻转前k个元素
        reverse(nums, k, n - 1)  # 第三步:翻转剩余元素


# 测试用例验证
if __name__ == "__main__":
    # 示例1:基础用例
    nums1 = [1, 2, 3, 4, 5, 6, 7]
    k1 = 3
    solution = Solution()
    print(f"原始数组1: {nums1}, 轮转步数k={k1}")
    solution.rotate(nums1, k1)
    print(f"轮转后数组1: {nums1}")  # 预期输出:[5,6,7,1,2,3,4]

    # 示例2:k大于数组长度的情况
    nums2 = [-1, -100, 3, 99]
    k2 = 2
    print(f"\n原始数组2: {nums2}, 轮转步数k={k2}")
    solution.rotate(nums2, k2)
    print(f"轮转后数组2: {nums2}")  # 预期输出:[3,99,-1,-100]

    # 边界用例1:空数组
    nums3 = []
    k3 = 5
    print(f"\n原始数组3: {nums3}, 轮转步数k={k3}")
    solution.rotate(nums3, k3)
    print(f"轮转后数组3: {nums3}")  # 预期输出:[]

    # 边界用例2:k=0(无需轮转)
    nums4 = [1, 2, 3]
    k4 = 0
    print(f"\n原始数组4: {nums4}, 轮转步数k={k4}")
    solution.rotate(nums4, k4)
    print(f"轮转后数组4: {nums4}")  # 预期输出:[1,2,3]

    # 边界用例3:数组长度为1
    nums5 = [10]
    k5 = 100
    print(f"\n原始数组5: {nums5}, 轮转步数k={k5}")
    solution.rotate(nums5, k5)
    print(f"轮转后数组5: {nums5}")  # 预期输出:[10]

LeetCode提交代码:

python 复制代码
class Solution:
    from typing import List
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        k %= n  # 处理k超过数组长度的情况
        
        # 定义翻转函数(双指针法,原地修改)
        def reverse(lst, start, end):
            while start < end:
                lst[start], lst[end] = lst[end], lst[start]
                start += 1
                end -= 1
        
        # 三次翻转
        reverse(nums, 0, n - 1)    # 翻转整个数组
        reverse(nums, 0, k - 1)    # 翻转前k个元素
        reverse(nums, k, n - 1)    # 翻转剩余元素

程序运行结果如下:

bash 复制代码
原始数组1: [1, 2, 3, 4, 5, 6, 7], 轮转步数k=3
轮转后数组1: [5, 6, 7, 1, 2, 3, 4]

原始数组2: [-1, -100, 3, 99], 轮转步数k=2
轮转后数组2: [3, 99, -1, -100]

原始数组3: [], 轮转步数k=5
轮转后数组3: []

原始数组4: [1, 2, 3], 轮转步数k=0
轮转后数组4: [1, 2, 3]

原始数组5: [10], 轮转步数k=100
轮转后数组5: [10]

总结

本文介绍了一种原地轮转数组的高效算法。通过三次翻转操作实现数组右移k位:首先计算有效轮转步数k=k%n,然后依次翻转整个数组、前k个元素和剩余元素。该方法时间复杂度O(n),空间复杂度O(1),适用于各种边界情况(空数组、k=0、k>n等)。Python实现采用双指针翻转函数,代码简洁高效,已通过LeetCode测试用例验证。

相关推荐
做怪小疯子2 小时前
华为笔试0429
python·numpy
Warson_L2 小时前
Dictionary
python
王老师青少年编程3 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【哈夫曼贪心】:合并果子
c++·算法·贪心·csp·信奥赛·哈夫曼贪心·合并果子
叼烟扛炮4 小时前
C++第二讲:类和对象(上)
数据结构·c++·算法·类和对象·struct·实例化
天疆说4 小时前
【哈密顿力学】深入解读航天器交会最优控制中的Hamilton函数
人工智能·算法·机器学习
寒山李白5 小时前
解决 python-docx 生成的 Word 文档打开时弹出“无法读取内容“警告
python·word·wps·文档·docx·qoder
wuweijianlove5 小时前
关于算法设计中的代价函数优化与约束求解的技术7
算法
leoufung5 小时前
LeetCode 149: Max Points on a Line - 解题思路详解
算法·leetcode·职场和发展
样例过了就是过了5 小时前
LeetCode热题100 最长公共子序列
c++·算法·leetcode·动态规划
2401_832365525 小时前
JavaScript中rest参数(...args)取代arguments的优势
jvm·数据库·python