Coderbyte中的练习应该确定数组中某些整数的子集是否与数组中的最大数相加。
以下代码似乎可以在我的计算机上运行,但是当我在线提交时,它似乎会导致无休止的循环。 (无论传递的参数如何,都没有任何输出。)
def arr_add?(arr)
a = arr.sort
lgst = a.pop
size = a.size
result = false
while size > 1
a.combination(size) {|c| result |= (c.inject {|r, a| r + a} == lgst)}
size -= 1
end
result.to_s
end
arr_add?([1, 2, 3, 4, 10, 14])
为什么会出现这种情况?
答案 0 :(得分:2)
我怀疑你实际上不正在进入无限循环,而是因为你的算法效率低下,所以只需要花费很长时间 。
def ArrayAdditionI(arr)
arr_size = arr.size
ary = arr.sort
largest = ary.pop
ary_size = arr_size - 1
combination_size = ary_size
result = false
while combination_size > 1
ary.combination(combination_size) {|combination|
result |= (combination.inject(
:+
) == largest)
}
combination_size -= 1
end
result.to_s
end
我引入了一个新变量并重命名了其他变量,以便更容易讨论该算法。我也重新格式化了它,使三个嵌套的#34;循环"更明显。
让我们来看看算法。
外部while
循环执行ary_size - 1 == arr_size - 2
次,combination_size
范围从2
到ary_size == arr_size - 1
。
combination
"循环"执行 ary_size
choose combination_size
次,这是一个非常快速增长的数字。
最里面的"循环" (由combination.inject
执行的操作)执行combination_size - 1
次。
这给出了最内部操作的总执行次数:
2
到arr_size - 1
的总和arr_size - 1
选择combination_size
次combination_size - 1
在Wolfram语言中,Wolfram Alpha告诉我们的Sum[Binomial[a-1, c]*(c-1), c, 2, a-1]
是2^(a-2) (a-3)+1
,它位于O(2 ^ n)。
稍微使用数字:
inject
操作尝试使用长度为5,10,15(所有瞬间),20(明显停顿),然后是23,24,25的数组的算法,以便快速感受如何运行时间增长。
假设您可以构建一个可以在单个指令中执行内部循环的CPU。进一步假设单个指令仅采用普朗克时间单位(即,CPU具有大约2000亿000 000 000 000 000 THz的频率)。进一步假设可观察宇宙中的每个粒子都是这样的CPU。对于甚至500个项目的数组执行算法,仍然需要超过当前的宇宙年龄。
请注意,对于大多数这些编程难题,它们不是实际编程难题,它们是数学难题。他们通常需要数学洞察力,以便能够有效地解决它们。或者,在这种情况下,识别它是Subset sum problem,已知它是NP完全的。
顺便说一句,作为一种风格问题,这里是用惯用Ruby风格编写的算法(略有不同)。正如您所看到的,在惯用的Ruby中,它几乎成为英语问题语句到代码的1:1翻译。
虽然它渐渐地和你的算法一样低效,但是一旦答案是true
,它就会提前中断(与你的不同,即使它已经找到了解决方案,它也会继续运行)。 (any?
会自动为您执行此操作。)
def ArrayAdditionI(arr)
largest = arr.delete_at(arr.index(arr.max))
1.upto(arr.size).any? {|combination_size|
arr.combination(combination_size).any? {|combination|
combination.inject(:+) == largest
}
}.to_s
end
这是对(不清楚)问题陈述的另一种解释:
def ArrayAdditionI(arr)
2.upto(arr.size).any? {|combination_size|
arr.combination(combination_size).any? {|combination|
combination.inject(:+) == arr.max
}
}.to_s
end
答案 1 :(得分:0)
上面的代码是有效的ruby代码。
结果是“真实”。
这有点不寻常,因为while循环有点罕见,但是因为它是有效的ruby代码,所以它也可以在远程站点上运行。
联系在Coderbyte运行在线红宝石翻译的人 - 他们的版本似乎与MRI红宝石不兼容。
你的代码似乎倒数了;或许看看10.downto(1) - 适当地替换变量。