返回
在 LeetCode 189 中巧解旋转数组难题
前端
2024-01-14 09:47:13
引言
在 LeetCode 189 中,我们面临着旋转数组的挑战,要求将给定数组中的元素向右移动 k 个位置。这看似简单的问题,却蕴含着巧妙的算法策略,本文将深入探讨三种不同的解决方案,为您提供全面的算法见解和编程指南。
1. 额外数组法:简单直接
最直接的方法是创建一个大小与原数组相同的额外数组,将原数组中的元素依次复制到新数组中,并根据移动位置 k 进行调整。这种方法易于理解和实现,但空间复杂度为 O(n)。
def rotate_extra_array(nums, k):
# 创建额外数组
new_nums = [0] * len(nums)
# 依次复制元素并调整位置
for i in range(len(nums)):
new_nums[(i + k) % len(nums)] = nums[i]
# 复制回原数组
for i in range(len(nums)):
nums[i] = new_nums[i]
2. 翻转数组法:巧妙高效
一种更巧妙的方法是使用翻转数组。我们可以先将整个数组翻转一次,再将数组的前 k 个元素和后 len(nums) - k 个元素分别翻转,即可达到旋转的目的。这种方法的时间复杂度为 O(n),空间复杂度为 O(1)。
def rotate_reverse_array(nums, k):
# 翻转整个数组
nums.reverse()
# 翻转前 k 个元素
nums[:k] = list(reversed(nums[:k]))
# 翻转后 len(nums) - k 个元素
nums[k:] = list(reversed(nums[k:]))
3. 最佳解法:环形替换
空间复杂度为 O(1) 的最佳解决方案采用环形替换的思想。我们使用一个循环来模拟数组的旋转,每一步将元素移动一个位置,直到元素回到起始位置。这种方法时间复杂度为 O(n),空间复杂度为 O(1)。
def rotate_ring_replacement(nums, k):
k %= len(nums)
start, count = 0, 0
while count < len(nums):
current, prev = start, nums[start]
while current != start:
next = (current + k) % len(nums)
nums[current] = nums[next]
current = next
count += 1
nums[current] = prev
start += 1
count += 1
结论
LeetCode 189 中的旋转数组难题提供了算法思维的绝佳练习。通过三种不同的解决方案,我们展示了额外数组法、翻转数组法和环形替换法的异同。对于不同的场景和需求,选择最合适的算法至关重要。本文深入剖析了这些方法的原理和实现,旨在为您的算法之旅提供启发和指导。