【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测试用例验证。

相关推荐
吴佳浩27 分钟前
GPU 编号进阶:CUDA\_VISIBLE\_DEVICES、多进程与容器化陷阱
人工智能·pytorch·python
Liu628881 小时前
C++中的工厂模式高级应用
开发语言·c++·算法
全栈凯哥1 小时前
18.Python中的导入类完全指南
python
AI科技星1 小时前
全尺度角速度统一:基于 v ≡ c 的纯推导与验证
c语言·开发语言·人工智能·opencv·算法·机器学习·数据挖掘
sunwenjian8861 小时前
Java进阶——IO 流
java·开发语言·python
参.商.1 小时前
【Day41】143. 重排链表
leetcode·golang
条tiao条2 小时前
KMP 算法详解:告别暴力匹配,让字符串匹配 “永不回头”
开发语言·算法
guts3502 小时前
图像篡改数据集下载:COVERAGE、CASIA
python·数据集
干啥啥不行,秃头第一名2 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
森林猿2 小时前
java-modbus-读取-modbus4j
java·网络·python