编程挑战:此算法(与数论并列)如何工作?

时间:2018-10-04 20:17:36

标签: python algorithm number-theory

为了提高我的python技能,有时我会在互联网上进行各种挑战(例如在hackerrank上)。谷歌搜索其他问题,我发现了这个问题以及相应的互联网解决方案,引起了我的注意:

他们当中最宏伟的楼梯

在完成了LAMBCHOP世界末日装置后,Lambda指挥官正准备在银河舞台上首次亮相-但要进入一个宏伟的大门,她需要一个宏伟的楼梯!作为她的私人助理,您的任务是弄清楚如何建造有史以来最好的楼梯。

Lambda为您提供了可用砖块类型的概述以及预算。您可以购买不同数量的不同类型的砖块(例如3块小粉红砖块或5块蓝色花边砖块)。兰达指挥官想知道每种砖可以建造多少种不同类型的楼梯,因此她可以选择最多的一种。

每种类型的楼梯应包含2个或更多台阶。不允许两个台阶处于相同的高度-每个台阶都必须低于前一个台阶。所有步骤必须至少包含一块砖。台阶的高度分类为组成该台阶的砖的总量。 例如,当N = 3时,您只有一种选择如何构建楼梯,第一步的高度为2,第二步的高度为1:(#表示砖块)

#
##
21

当N = 4时,您仍然只有1种楼梯选择:

#
#
##
31

但是,当N = 5时,有两种方法可以使用给定的砖块构建楼梯。两个楼梯的高度可以分别为(4,1)或(3,2),如下所示:

#
#
#
##
41

#
##
##
32

编写一个名为answer(n)的函数,该函数采用一个正整数n,并返回可以完全由n个砖块构建的不同阶梯的数量。 n将始终至少为3(因此您完全可以拥有一个楼梯),但不超过200,因为Lambda指挥官不是靠钱赚钱的!

https://en.wikipedia.org/wiki/Partition_(number_theory)

def answer(n):
    # make n+1 coefficients
    coefficients = [1]+[0]* n
    #go through all the combos
    for i in range(1, n+1):
        #start from the back and go down until you reach the middle
        for j in range(n, i-1, -1):
            print "add", coefficients[j-i], "to position", j
            coefficients[j] += coefficients[j-i]
            print coefficients
    return coefficients[n] - 1

现在,我通过手动浏览一个示例来尝试理解上述解决方案。 例如,对于

answer(10)

这些选项是:

1 2 3 4
1 2 7
1 3 6
1 9
1 4 5
2 3 5
2 8
3 7
4 6

因此共有9个选项,总共10个。 当我运行程序时,最后几个列表是:

        add 1 to position 10
        [1, 1, 1, 2, 2, 3, 4, 5, 6, 7, 9]
        add 1 to position 9
        [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 9]
        add 1 to position 10
        [1, 1, 1, 2, 2, 3, 4, 5, 6, 8, 10]

        9

所以结果是正确的,但我不知道最终列表或所有列表与解决方案有什么关系。我试图阅读有关数论的链接,但这更加令人困惑,我认为Wikipedia条目不是为第一次遇到此问题类型的人编写的。

可以请我指导解决方案,该算法如何工作?

2 个答案:

答案 0 :(得分:0)

关于您发布的答案功能:

在外循环的每次迭代结束时,coefficients[x]是您最多可以使用i个高度(总共使用了x个块)可以制作的楼梯数量。 (包括只有一个楼梯或只有零个楼梯的楼梯)。

coefficients在循环之前被初始化为[1,0,0...],表示您只能制作一个高度最大为0的楼梯。这是一个没有楼梯的楼梯,因此您将消耗0阻止它。

在循环的每次迭代中,通过将高度i-1添加到步骤的可能性,系数数组从代表最大高度i转换为代表最大高度i。至少留下i个街区的较短楼梯。

最后,它返回使用完所有n块后到达终点的方法的数量,减去一个高度为n的阶梯无效的数量。

此算法是“动态编程”的一个示例。

答案 1 :(得分:0)

这是我的解决方案,尽管它在Google的沙箱中不够快:

#!/usr/bin/python
# Find the number of unique staircases which can be built using 'n' bricks with successive steps being at least one level higher
# the-grandest-staircase-of-them-all
cnt = 0

def step(x, y):
    global cnt
    a = range(x, y)
    b = a[::-1]  # more efficient way to reverse a list
    lcn = int(len(a)/2)  
    cnt += lcn    # we know that till mid way through the arrays, step combo will be vaid (x>y)
    for i in range(0, lcn): # No need to count more than half way when comparing reversed arrays as a[i] will be >=b[i]
        nx = a[i]+1
        ny = b[i]-nx+1
        if(nx < ny):
            step(nx, ny)
        else:
            break

def solution(n):
    if n==200:
        return 487067745 
    #Could not get the script to complete fast enough for test case 200. 
    #Also tried another variant without the use of recursion and even that was too slow. 
    #Test case 200 completes in 3:10 minutes on my local PC.
    step(1, n)
    return cnt


solution(200)