Python算法题集_轮转数组

 Python算法题集_题目:轮转数组

  • 题目189:轮转数组
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【双切片】
    • 2) 改进版一【直接赋值】
    • 3) 改进版二【三次反转】
    • 4) 无冕之王【切片合并】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题目189:轮转数组

1. 示例说明

  • 说明:给定一个整数数组 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

2. 题目解析

- 题意分解

  1. 本题为求数组元素的移动
  2. 最笨的办法是挨个赋值,单层循环,所以基本的时间算法复杂度为O(n)

- 优化思路

  1. 通常优化:减少循环层次

  2. 通常优化:增加分支,减少计算集

  3. 通常优化:采用内置算法、内置数据类型来提升计算速度

  4. 分析题目特点,分析最优解

    1)本题最简单的解法为数组切片连接【链表切片、连接都是(O(1))】,但是网站不能运行,只能自己测试

    2)建立两个切片副本,循环更新元素是标准做法

    3)建立数组副本,直接计算下标在循环中更新元素,减少一次切片操作

    4)实施数组的反转操作,可以不用建立数据缓冲,直接完成更新


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块
  • 本题很难超时,本地化超时测试用例自己生成,详见【最优算法章节】

3. 代码展开

1) 标准求解【双切片】

仅仅通过,超过12%Python算法题集_轮转数组_第1张图片

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

2) 改进版一【直接赋值】

飞龙在天,超越97%Python算法题集_轮转数组_第2张图片

简单改进,取得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

3) 改进版二【三次反转】

表现优良,超越86%Python算法题集_轮转数组_第3张图片

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

4) 无冕之王【切片合并】

此题虽然不认这个解法,但还是无冕之王 ,无论数组多大,都只要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. 最优算法

根据本地日志分析,最优算法为第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 ~

你可能感兴趣的:(Python,算法,python,开发语言,leetcode,数组)