递归和迭代的差异
简单对比一下递归和迭代的差异,针对全排列问题,一个用递归实现,一个用迭代(深度优先,广度优先)的方式分别实现,均在相同计算机环境下比较。
计算机 | 配置 |
---|---|
处理器 | Intel® Core™ i7-8700K CPU @ 3.70GHz,3696 Mhz,6 个内核,12 线程 |
总的物理内存 | 16.0 GB |
题目:力扣-46.全排列
给定一个不含重复数字的数组 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]]
实验:
依次测试[1],[1,2],[1,2,3],…,[1,…,10]算例,记录两个方法所用时间,结果如图所示。算法运行时间限制60s,超过即停止。
结论: 迭代(深度优先)和递归差不多,与预期相符;迭代(广度优先)速度差很多,代码实现是一方面,广度优先循环次数远远多余前面两者。总体而言:
- 递归现实最为简洁,没有无效搜索,缺点是难以debug,问题复杂以后需要一定经验;
- 迭代(深度优先)教易理解和调试,推荐;
- 迭代(广度优先)慎用!!!
实验代码:
from time import time
import matplotlib.pyplot as plt
from tqdm import trange
def recursion(nums):
'递归'
res = []
def backtrack(nums, tmp):
if not nums:
res.append(tmp)
return
for i in range(len(nums)):
backtrack(nums[:i] + nums[i+1:], tmp + [nums[i]])
backtrack(nums, [])
return res
def iteration_dfs(nums):
'迭代循环 —— 深度优先'
res = []
Queue = [[i] for i in nums]
while Queue:
q = Queue.pop(-1)
if len(q) == len(nums):
res.append(q)
continue
for i in nums:
if i not in q:
q_ = q[:]
q_.append(i)
if q_ not in Queue:
Queue.append(q_)
return res
def iteration_bfs(nums):
'迭代循环 —— 广度优先'
res = []
Queue = [[i] for i in nums]
while Queue:
q = Queue.pop(0)
if len(q) == len(nums):
res.append(q)
continue
for i in nums:
if i not in q:
q_ = q[:]
q_.append(i)
if q_ not in Queue:
Queue.append(q_)
return res
x = list(range(1,11))
y1 = []
y2 = []
for i in trange(1,11):
input = list(range(i))
s1 = time()
res1 = recursion(input)
s1time = time()-s1
y1.append(s1time)
s2 = time()
res2 = iteration_dfs(input)
s2time = time()-s2
y2.append(s2time)
s3 = time()
res3 = iteration_bfs(input)
s3time = time()-s3
y3.append(s3time)
plt.plot(x,y1,color='b',label='recursion')
plt.plot(x,y2,color='g',label='iteration_dfs')
plt.plot(x,y3,color='r',label='iteration_bfs')
plt.legend()
plt.xlabel('问题规模')
plt.ylabel('时间(s)')
# plt.savefig('results.jpg')