使用python从10到N的步骤数

使用python从10到N的步骤数,python,python-3.x,Python,Python 3.x,程序必须接受整数N。程序必须打印从10到N的所有步进数,如果没有这样的数字,程序应打印-1作为输出 如果所有相邻数字的绝对差为1,则称为步进数 代码工作正常我只需要减少最大可能测试用例的时间限制 我用python编写了代码,在那里我使用了暴力来解决这个问题,但是由于时间限制,代码没有成功 有没有办法减少执行时间?提前感谢您可以通过以下方式简化数字的生成:每次向现有步进数字添加一个数字时,该数字必须比现有的最后一个数字多1或少1。因此,我们可以通过从单个数字(1-9)开始,然后重复向它们添加

程序必须接受整数N。程序必须打印从10到N的所有步进数,如果没有这样的数字,程序应打印-1作为输出

如果所有相邻数字的绝对差为1,则称为步进数
代码工作正常
我只需要减少
最大可能测试用例的时间限制
我用python编写了代码,在那里我使用了
暴力
来解决这个问题,但是由于时间限制,代码没有成功




有没有办法减少执行时间?提前感谢

您可以通过以下方式简化数字的生成:每次向现有步进数字添加一个数字时,该数字必须比现有的最后一个数字多1或少1。因此,我们可以通过从单个数字(1-9)开始,然后重复向它们添加数字,直到达到所需的位数为止,生成具有给定位数的所有步进数。例如,从数字
1
开始,需要到4位,我们将生成

1 => 10, 12
10, 12 => 101, 121, 123
101, 121, 123 => 1010, 1012, 1210, 1212, 1232, 1234
我们需要的位数是使用
math.ceil(math.log10(N))
计算的

输出:

[10, 12, 21, 23, 32, 34, 43, 45, 54, 56, 65, 67, 76, 78, 87, 89, 98, 101, 121, 123, 210, 212, 232, 234, 321, 323, 343, 345, 432, 434, 454, 456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 987, 989, 1010, 1012, 1210, 1212, 1232, 1234, 2101, 2121, 2123, 2321, 2323, 2343, 2345, 3210, 3212, 3232, 3234, 3432, 3434, 3454]

请注意,通过将生成的数字与
N
进行比较,可以潜在地加快代码的速度,以便在调用
stepNums(10001)
时,我们不会生成所有小于
98989

的数字。这里的主要技巧可能是最大范围为10^7。如果我们把每个数字看作是图的一个节点,我们可以用BFS/DFS遍历它,并且在每个点,我们只能移动到相邻的节点(数字+ 1,数字- 1)。因为最大深度只有7,所以解决方案应该非常快

这是一个粗略的DFS实现,您可以改进细节

sol_list = []
def dfs(i, num, N):
  # print(i, num)
  if num > N: # too much, need to break
    return
  if num <= N and num >= 10: # perfect range, add to solution, I can add some repeated solution as I called dfs(i+1,0,N) multiple times
    global sol_list
    # print(num)
    sol_list.append(num) # add to solution

  if i > 7:
    return
  if num == 0: # I can call another 0
    dfs(i+1, 0, N) # this is not needed if the numbers are added in the previous list without checking
  last_dig = num % 10
  if last_dig == 0:
      dfs(i+1, num*10 + 1, N) # if last digit is 0, we can only choose 1 as next digit not -1
  elif last_dig == 9:
    dfs(i+1, num*10 + 8, N)
  else:
    dfs(i+1, num*10 + (last_dig-1), N)
    dfs(i+1, num*10 + (last_dig+1), N)

import time
t1 = time.time()
[dfs(0, i, 10000000) for i in range(10)] # staring with every digit possible 0-9
t2 = time.time()
print(t2-t1)
sol = sorted(set(sol_list))
print(sol) # added some repeated solutions, it's easier to set them
sol_list=[]
def dfs(i、num、N):
#打印(i,num)
如果num>N:#太多,需要中断
回来
如果num=10:#完美范围,添加到解决方案中,我可以添加一些重复的解决方案,就像我多次调用dfs(I+1,0,N)一样
全球解决方案清单
#打印(个)
sol_list.append(num)#添加到解决方案
如果i>7:
回来
如果num==0:#我可以调用另一个0
dfs(i+1,0,N)#如果未经检查就将数字添加到上一个列表中,则不需要此选项
上次挖掘=数量%10
如果last_dig==0:
dfs(i+1,num*10+1,N)#如果最后一个数字是0,我们只能选择1作为下一个数字,而不是-1
elif last_dig==9:
dfs(i+1,数量*10+8,N)
其他:
dfs(i+1,数量*10+(最后一次挖掘),N)
dfs(i+1,数值*10+(最后一次挖掘+1),N)
导入时间
t1=时间。时间()
[dfs(0,i,10000000)用于范围(10)内的i]#以每一个可能的数字0-9开始
t2=时间。时间()
打印(t2-t1)
sol=已排序(集合(sol_列表))
print(sol)#添加了一些重复的解决方案,设置起来更容易

因为我还不能发表评论。我将在这里解释尼克算法的思想

  • 创建一位数字列表
    [1,2,3,4,5,6,7,8,9]

  • 通过将1位数字列表中的数字
    k
    与k*10+(k-1)或k*10+(k+1)组合,创建2位数字列表,例如
    3
    将生成
    32
    34

  • 重复步骤2,直到达到m位数字
    m
    在之前计算过
  • 来自itertools导入产品的
    
    从itertools导入
    导入时间
    def干管(n):
    结果=集合()
    对于范围(2,7)内的长度:
    dxss=列表(产品([-1,1],重复=长度-1))
    对于范围(1,10)内的初始值:
    对于dxss中的dxs:
    ans=列表(累积(dxs,初始值=初始值))
    如果ans中y的所有([(y在范围(0,10))为):
    结果.add(int(“.join(map(str,ans)))
    已排序\u lst=已排序(结果)
    
    回来[x代表排序后的x_lst如果您能用文字解释您的算法吗?您是否需要按排序后的顺序返回数据?120和160的输出应该是什么样子?@zedfoxus对于120,它应该是
    10 12 21 23 32 34 43 45 54 56 67 76 78 89 98 101
    对于160,它应该是
    10 12 21 23 32 34 45 56 67 76 87 8998 101 121 123
    @Nick是的,它需要分类。您能解释一下这个程序吗,请输入代码,@Nick!!谢谢分享。我所走的路线与记忆12的路线类似,例如,翻转数字得到21,然后向前跳。您的解决方案非常有效。@Altair请查看我的编辑,我添加了一个解释我希望这一点是明确的。非常好。你只需要在最后对它进行排序,并确保数字不会重复。我的代码似乎比这快2-3倍,可能是因为所有函数调用的开销。是的,但它仍然在时间限制下。对我来说,我觉得dfs更直观,我肯定可以优化dfs,但你可以你的解决方案在速度方面更好。只有一般答案是不鼓励的。请考虑解释你的方法。
    Input : 100
    Output: 10 12 21 23 32 34 43 45 54 56 65 67 76 78 87 89 98
    
    Input : 5
    Output : -1
    
    1 => 10, 12
    10, 12 => 101, 121, 123
    101, 121, 123 => 1010, 1012, 1210, 1212, 1232, 1234
    
    import math
    
    def stepNums(N):
        if N < 10:
            return -1
        digits = math.ceil(math.log10(N))
        sn = [[]] * digits
        # 1 digit stepping numbers
        sn[0] = list(range(1, 10))
        # m digit stepping numbers
        for m in range(1, digits):
            sn[m] = []
            for s in sn[m-1]:
                if s % 10 != 0:
                    sn[m].append(s * 10 + s % 10 - 1)
                if s % 10 != 9:
                    sn[m].append(s * 10 + s % 10 + 1)
        return [s for l in sn for s in l if 10 <= s <= N]
    
    print(stepNums(3454))
    
    [10, 12, 21, 23, 32, 34, 43, 45, 54, 56, 65, 67, 76, 78, 87, 89, 98, 101, 121, 123, 210, 212, 232, 234, 321, 323, 343, 345, 432, 434, 454, 456, 543, 545, 565, 567, 654, 656, 676, 678, 765, 767, 787, 789, 876, 878, 898, 987, 989, 1010, 1012, 1210, 1212, 1232, 1234, 2101, 2121, 2123, 2321, 2323, 2343, 2345, 3210, 3212, 3232, 3234, 3432, 3434, 3454]
    
    sol_list = []
    def dfs(i, num, N):
      # print(i, num)
      if num > N: # too much, need to break
        return
      if num <= N and num >= 10: # perfect range, add to solution, I can add some repeated solution as I called dfs(i+1,0,N) multiple times
        global sol_list
        # print(num)
        sol_list.append(num) # add to solution
    
      if i > 7:
        return
      if num == 0: # I can call another 0
        dfs(i+1, 0, N) # this is not needed if the numbers are added in the previous list without checking
      last_dig = num % 10
      if last_dig == 0:
          dfs(i+1, num*10 + 1, N) # if last digit is 0, we can only choose 1 as next digit not -1
      elif last_dig == 9:
        dfs(i+1, num*10 + 8, N)
      else:
        dfs(i+1, num*10 + (last_dig-1), N)
        dfs(i+1, num*10 + (last_dig+1), N)
    
    import time
    t1 = time.time()
    [dfs(0, i, 10000000) for i in range(10)] # staring with every digit possible 0-9
    t2 = time.time()
    print(t2-t1)
    sol = sorted(set(sol_list))
    print(sol) # added some repeated solutions, it's easier to set them
    
    from itertools import product
    from itertools import accumulate
    import time
    
    def main(n):
        result=set()
        for length in range(2,7):
            dxss=list(product([-1,1],repeat=length-1))
            for initial in range(1,10):
                for dxs in dxss:
                    ans=list(accumulate(dxs,initial=initial))
                    if all([(y in range(0,10)) for y in ans]):
                         result.add(int("".join(map(str,ans))))
        sorted_lst=sorted(result)
        return [x for x in sorted_lst if x<n]
    
    n=10000000
    start=time.time()
    lst=main(n)
    stop=time.time()
    print("time={0}[s]".format(stop-start))
    print(lst)