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

相关推荐
Aspect of twilight2 小时前
LeetCode华为2025年秋招AI大模型岗刷题(四)
算法·leetcode·职场和发展
这个人懒得名字都没写9 小时前
Python包管理新纪元:uv
python·conda·pip·uv
有泽改之_9 小时前
leetcode146、OrderedDict与lru_cache
python·leetcode·链表
im_AMBER9 小时前
Leetcode 74 K 和数对的最大数目
数据结构·笔记·学习·算法·leetcode
是毛毛吧9 小时前
边打游戏边学Python的5个开源项目
python·开源·github·开源软件·pygame
t198751289 小时前
电力系统经典节点系统潮流计算MATLAB实现
人工智能·算法·matlab
断剑zou天涯9 小时前
【算法笔记】蓄水池算法
笔记·算法
三途河畔人10 小时前
Pytho基础语法_运算符
开发语言·python·入门