Python算法题集_全排列
- 题46:全排列
- 1. 示例说明
- 2. 题目解析
- - 题意分解
- - 优化思路
- - 测量工具
- 3. 代码展开
- 1) 标准求解【标记数组+递归】
- 2) 改进版一【指针+递归】
- 3) 改进版二【高效迭代模块】
- 4) 改进版三【高效迭代模块+极简代码】
- 4. 最优算法
- 5. 相关资源
本文为Python算法题集之一的代码示例
题46:全排列
1. 示例说明
-
给定一个不含重复数字的数组
nums
,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。示例 1:
输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
示例 2:
输入:nums = [0,1] 输出:[[0,1],[1,0]]
示例 3:
输入:nums = [1] 输出:[[1]]
提示:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
nums
中的所有整数 互不相同
2. 题目解析
- 题意分解
- 本题是计算集合的全排列组合
- 基本的设计思路是递归计算组合
- 优化思路
-
通常优化:减少循环层次
-
通常优化:增加分支,减少计算集
-
通常优化:采用内置算法来提升计算速度
-
分析题目特点,分析最优解
-
每加一个元素,添加的组合等于旧元素全排列集合与新元素各排列一次,以此递归
-
可以考虑用高效迭代模块单元
itertools
-
- 测量工具
- 本地化测试说明:LeetCode网站测试运行时数据波动很大【可把页面视为功能测试】,因此需要本地化测试解决数据波动问题
CheckFuncPerf
(本地化函数用时和内存占用测试模块)已上传到CSDN,地址:Python算法题集_检测函数用时和内存占用的模块- 本题本地化超时测试用例自己生成,详见章节【最优算法】,代码文件包含在【相关资源】中
3. 代码展开
1) 标准求解【标记数组+递归】
使用标记数组记录前置组合,递归求解
页面功能测试,马马虎虎,超过54%
import CheckFuncPerf as cfp
class Solution:
def permute_base(self, nums):
paths = []
ilen = len(nums)
def dfspermute(nums, path):
if len(path) == ilen:
paths.append(path[:])
return
for num in nums:
pathleft = path[:]
pathleft.append(num)
numsresidue = nums[:]
numsresidue.remove(num)
dfspermute(numsresidue, pathleft)
dfspermute(nums, [])
return paths
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.permute_base, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 permute_base 的运行时间为 6231.28 ms;内存使用量为 549252.00 KB 执行结果 = 3628800
2) 改进版一【指针+递归】
使用指针标记数组记录前置位置,递归求解
页面功能测试,性能卓越,超越95%
import CheckFuncPerf as cfp
class Solution:
def permute_ext1(self, nums):
def permutation_sub(ls, start, result):
if start == len(ls) - 1:
result.append(list(ls))
return
for i in range(start, len(ls)):
ls[i], ls[start] = ls[start], ls[i]
permutation_sub(ls, start + 1, result)
ls[i], ls[start] = ls[start], ls[i]
perm = []
permutation_sub(nums, 0, perm)
return perm
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.permute_ext1, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 permute_ext1 的运行时间为 4993.29 ms;内存使用量为 760188.00 KB 执行结果 = 3628800
3) 改进版二【高效迭代模块】
使用高效迭代模块itertool
的迭代器直接实现全排列功能
页面功能测试,性能良好,超过90%
import CheckFuncPerf as cfp
class Solution:
def permute_ext2(self, nums):
import itertools
list_result = []
for perm in itertools.permutations(nums):
list_result.append(list(perm))
return list_result
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.permute_ext2, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 permute_ext2 的运行时间为 2189.55 ms;内存使用量为 759268.00 KB 执行结果 = 3628800
4) 改进版三【高效迭代模块+极简代码】
使用高效迭代模块itertool
的迭代器,直接一行生成结果,减少中间变量
页面功能测试,马马虎虎,超过46%
import CheckFuncPerf as cfp
class Solution:
def permute_ext3(self, nums):
import itertools
return [list(perm) for perm in itertools.permutations(nums)]
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.permute_ext3, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 运行结果
函数 permute_ext3 的运行时间为 2016.28 ms;内存使用量为 759028.00 KB 执行结果 = 3628800
4. 最优算法
根据本地日志分析,最优算法为第4种方式【高效迭代模块+极简代码】permute_ext3
本题测试数据,似乎能推出以下结论:
- 减少操作的独立变量,可以提升极限性能【未必可保证可读性】
itertool
模块应该是用C等语言实现,效率远高于Python代码逐行实现
nums = [x for x in range(10)]
aSolution = Solution()
result = cfp.getTimeMemoryStr(aSolution.permute_base, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.permute_ext1, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.permute_ext2, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
result = cfp.getTimeMemoryStr(aSolution.permute_ext3, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))
# 算法本地速度实测比较
函数 permute_base 的运行时间为 6231.28 ms;内存使用量为 549252.00 KB 执行结果 = 3628800
函数 permute_ext1 的运行时间为 4993.29 ms;内存使用量为 760188.00 KB 执行结果 = 3628800
函数 permute_ext2 的运行时间为 2189.55 ms;内存使用量为 759268.00 KB 执行结果 = 3628800
函数 permute_ext3 的运行时间为 2016.28 ms;内存使用量为 759028.00 KB 执行结果 = 3628800
5. 相关资源
本文代码已上传到CSDN,地址:Python算法题源代码_LeetCode(力扣)_全排列
一日练,一日功,一日不练十日空
may the odds be ever in your favor ~