本文为Python算法题集之一的代码示例
说明:给定一个整数数组 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 <= 105
-231 <= nums[i] <= 231 - 1
0 <= k <= 105
通常优化:减少循环层次
通常优化:增加分支,减少计算集
通常优化:采用内置算法、内置数据类型来提升计算速度
分析题目特点,分析最优解
1)本题最简单的解法为数组切片连接【链表切片、连接都是(O(1))】,但是网站不能运行,只能自己测试
2)建立两个切片副本,循环更新元素是标准做法
3)建立数组副本,直接计算下标在循环中更新元素,减少一次切片操作
4)实施数组的反转操作,可以不用建立数据缓冲,直接完成更新
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块import CheckFuncPerf as cfp
def rotate_base(nums, k):
kx = k % len(nums)
list1 = nums[:len(nums) - kx]
list2 = nums[len(nums) - kx:]
iIdx = 0
while list2:
nums[iIdx] = list2.pop(0)
iIdx += 1
while list1:
nums[iIdx] = list1.pop(0)
iIdx += 1
return nums
import random
nums = []
for iIdx in range(100000):
nums.append(random.randint(0, 10000))
k = 1357
result = cfp.getTimeMemoryStr(rotate_base, nums, k)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 rotate_base 的运行时间为 886.20 ms;内存使用量为 860.00 KB 执行结果 = 100000
简单改进,取得97%的性能,说明本题改进的空间不大
import CheckFuncPerf as cfp
def rotate_ext1(nums, k) :
numscopy = nums.copy()
kx = k % len(nums)
for iIdx in range(len(nums)):
nums[iIdx] = numscopy[iIdx-kx]
return nums
import random
nums=[]
for iIdx in range(100000):
nums.append(random.randint(0, 10000))
k = 1357
result = cfp.getTimeMemoryStr(rotate_ext1, nums, k)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 rotate_ext1 的运行时间为 8.00 ms;内存使用量为 4.00 KB 执行结果 = 100000
import CheckFuncPerf as cfp
def rotate_ext2(nums, k):
nums.reverse()
kx = k % len(nums)
len1, len2 = kx // 2, (len(nums)-kx) // 2
for iIdx in range(len1):
nums[iIdx], nums[kx-iIdx-1] = nums[kx-iIdx-1], nums[iIdx]
for iIdx in range(len2):
nums[kx+iIdx], nums[-iIdx-1] = nums[-iIdx-1], nums[kx+iIdx]
return nums
import random
nums=[]
for iIdx in range(100000):
nums.append(random.randint(0, 10000))
k = 1357
result = cfp.getTimeMemoryStr(rotate_ext2, nums, k)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 rotate_ext2 的运行时间为 11.99 ms;内存使用量为 0.00 KB 执行结果 = 100000
此题虽然不认这个解法,但还是无冕之王 ,无论数组多大,都只要1毫秒
import CheckFuncPerf as cfp
def rotate_ext3(nums, k):
kx = k % len(nums)
list1 = nums[:len(nums)-kx]
list2 = nums[len(nums)-kx:]
nums = list2 + list1
return nums
import random
nums=[]
for iIdx in range(100000):
nums.append(random.randint(0, 10000))
k = 1357
result = cfp.getTimeMemoryStr(rotate_ext3, nums, k)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 rotate_ext3 的运行时间为 1.00 ms;内存使用量为 792.00 KB 执行结果 = 100000
根据本地日志分析,最优算法为第4种rotate_ext3
import random
nums=[]
for iIdx in range(100000):
nums.append(random.randint(0, 10000))
k = 1357
result = cfp.getTimeMemoryStr(rotate_ext2, nums, k)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 算法本地速度实测比较
函数 rotate_base 的运行时间为 886.20 ms;内存使用量为 860.00 KB 执行结果 = 100000
函数 rotate_ext1 的运行时间为 8.00 ms;内存使用量为 4.00 KB 执行结果 = 100000
函数 rotate_ext2 的运行时间为 11.99 ms;内存使用量为 0.00 KB 执行结果 = 100000
函数 rotate_ext3 的运行时间为 1.00 ms;内存使用量为 792.00 KB 执行结果 = 100000
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~