给定一个正整数'n',找到并返回'n'要减少到1所需的最小步骤数。您可以执行以下3个步骤中的任何一个:
1.减去1。(n = n -1)
1.如果n可被2整除,则除以2。(如果n % 2 == 0,则n = n / 2)
1.如果n能被3整除,就除以3。(如果n % 3 == 0,则n = n / 3)
输入格式:
输入的第一行也是唯一的一行包含一个整数值“n”。
输出格式:
打印最小步数。
制约因素:
1 <= n <= 10 ^ 6
时间限制:1秒
以下为代码
from sys import maxsize as MAX_VALUE
dic = {}
def countMinStepsToOne(n) :
if n == 1:
return 0
if n % 3 == 0:
if n/3 not in dic:
dic[n/3] = countMinStepsToOne(n/3)
if n % 2 == 0:
if n/2 not in dic:
dic[n/2] = countMinStepsToOne(n/2)
if n-1 not in dic:
dic[n-1] = countMinStepsToOne(n-1)
return 1 + min(dic.get(n/3,MAX_VALUE),dic.get(n/2,MAX_VALUE),dic.get(n-1,MAX_VALUE))
#main
n = int(input())
print(countMinStepsToOne(n))
**对于n的小值,它给出了正确的输出,但当我尝试更大的值时,让我们取5685,powershell杀死没有输出的进程,在jupyter notebook内核中死亡。
据我所知,我认为字典是造成问题的原因,因为当我试图打印dic
它是空的,但仍然没有得到它是如何工作的较小的值,而不是较大的。
1条答案
按热度按时间7eumitmz1#
递归地做这件事意味着你本质上是在做一个可能性空间的DFS,这将创建一个非常深的堆栈(当在一个大输入上运行你的代码时,我得到了一个
RecursionError
),并且可能会浪费大量时间计算非常长的路径,你最终会重新计算以找到一个更短的路径到相同的值。输入越大,这种效果越差。我建议将此作为BFS来执行,例如:
这非常快速地返回输入5685的结果15。
在每次迭代中,
level
是搜索空间的当前级别,depth
是我们到目前为止遍历的级别数。我们跟踪
visited
,以便如果我们在上一个搜索路径中已经访问过的值处结束,我们可以快速忽略它(例如如果我们沿着n - 1
路径前进,发现了一个我们已经能够以更快的方式获得的值,那么从该点重新计算路径就没有意义了)。我们不需要一个dict来跟踪我们找到这个值时的深度,我们只需要知道它是一个已经在探索过程中的可能性。如果我们在
while
循环的底部添加一个print
:我们可以看到在BFS的每个级别上正在探索的内容: