【问题标题】:programming challenge: how does this algorithm (tied to Number Theory) work?编程挑战:这个算法(与数论相关)是如何工作的?
【发布时间】:2018-10-04 20:17:36
【问题描述】:

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

最宏伟的楼梯

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

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

每种类型的楼梯都应由 2 个或更多台阶组成。不允许两个台阶处于相同高度 - 每个台阶必须低于前一个台阶。所有台阶必须包含至少一块砖。台阶的高度被归类为构成该台阶的砖的总量。 例如,当 N = 3 时,您只有 1 个选择如何建造楼梯,第一步高度为 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

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

谁能告诉我解决方案,算法是如何工作的?

【问题讨论】:

  • 欢迎来到 StackOverflow。请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 On topichow to ask... the perfect question 在此处申请。 StackOverflow 不是设计、编码、研究或教程资源。
  • 链接文章的相关部分是here。请注意,当算法完成时,数组包含 OEIS 序列。减去一个的原因是增加了楼梯必须至少有两个台阶的要求。
  • 请给您的问题一个更具描述性的标题。
  • 我隐约记得在开始同样的挑战时同意不发布这些问题。硬币分配问题是否足够相似,可以用这个问题来代替?
  • 这比我的答案要严格得多,尽管至少我理解我的答案:)

标签: python algorithm number-theory


【解决方案1】:

关于您发布的答案功能:

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

coefficients在循环之前被初始化为[1,0,0...],表示你只能做一个高度最多为0的楼梯。这是没有楼梯的,所以你会消耗0个方块来完成它.

在循环的每次迭代中,系数数组从表示最大高度i-1 转换为表示最大高度i,方法是将高度为i 的台阶添加到离开您的任何较短的楼梯的可能性至少有 i 块。

最后,它返回在使用完所有 n 块后您可以到达终点的方式数,减一,因为高度为 n 的单个楼梯无效。

这个算法是“动态规划”的一个例子。

【讨论】:

  • “在任何较短的楼梯上添加一个高度为 i 的台阶的可能性,使您至少有 i 块”——你能用一些例子来解释一下吗?我得到了动态编程、记忆化的所有想法,但仍然很难理解这部分。谢谢!
【解决方案2】:

此解决方案是dynamic programming 的示例。

def grandStair(n):
    table = [1] + [0]*(n)
    for brick in range(1, n+1):
        for height in range(n, brick-1, -1):
            table[height] += table[height - brick]
    return table[-1]-1

为了理解这一点,尝试在每次迭代后打印出表格。我强烈建议您使用 draw 并手动填充此表。

考虑n=6

grandStair(6) = 3

有 3 种方法可以制作高度总和为 6 的楼梯: (1,2,3), (1,5), (2,4)

这是每次迭代后表格的样子

[1, 0, 0, 0, 0, 0, 0]
[1, 1, 0, 0, 0, 0, 0]
[1, 1, 1, 1, 0, 0, 0]
[1, 1, 1, 2, 1, 1, 1]
[1, 1, 1, 2, 2, 2, 2]
[1, 1, 1, 2, 2, 3, 3]
[1, 1, 1, 2, 2, 3, 4]

我们从高度为 0 的砖块开始,逐步构建到从 0 到 n 的砖块。

【讨论】:

  • 我不明白您打印出来的表格如何反映楼梯。例如,最后一行 [1, 1, 1, 2, 2, 3, 4] 的总和大于 6。
【解决方案3】:

这是我的解决方案,虽然它在 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)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多