我正在研究Leetcode的以下算法:
Numbers can be regarded as product of its factors. For example,
8 = 2 x 2 x 2;
= 2 x 4.
Write a function that takes an integer n and return all possible combinations of its factors.
Note:
You may assume that n is always positive.
Factors should be greater than 1 and less than n.
Examples:
input: 1
output:
[]
input: 37
output:
[]
input: 12
output:
[
[2, 6],
[2, 2, 3],
[3, 4]
]
input: 32
output:
[
[2, 16],
[2, 2, 8],
[2, 2, 2, 4],
[2, 2, 2, 2, 2],
[2, 4, 4],
[4, 8]
]
这是我到目前为止的代码:
def get_factors(n)
factors = []
(2...n).each do |candidate|
if n % candidate == 0
factors << [candidate, (n/candidate)]
get_factors(n/candidate).each do |factor_set|
factors << [candidate] + factor_set
end
end
end
factors
end
此代码工作得很好,但不处理重复(例如[3,2,2]将与[2,2,3]一起插入)。我尝试使用带有以下代码的Set
def get_factors(n)
seen = Set.new
factors = []
(2...n).each do |candidate|
if n % candidate == 0 && !seen.include?(candidate)
factors << [candidate, (n/candidate)]
get_factors(n/candidate).each do |factor_set|
factors << [candidate] + factor_set
end
end
seen << (n/candidate)
end
factors
end
但这仅适用于解决某些测试用例而非其他测试用例。我不确定如何以有效的方式确保没有重复?真正低效的方法是根据每个数组的元素(并且不依赖于顺序)为每个数组生成某种哈希值,虽然这样可行,但肯定应该有更好的方法。有什么想法吗?
答案 0 :(得分:0)
我认为永远向前推进是一个很好的政策(例如,当用5检查时,不要用2,3,4等检查)。这样,可以消除搜索重复项。
答案 1 :(得分:0)
由于算法已经占用了大量时间,因此我没有看到排序每个答案并删除重复的问题。这不需要证明它确实有效,mac提供的答案就是这样。
答案 2 :(得分:0)
<强>代码强>
require 'prime'
def get_factors(n)
primes, nbr = Prime.prime_division(n).transpose
powers = nbr.map { |m| (0..m).to_a }
powers.shift.
product(*powers).
map { |pows| primes.zip(pows).reduce(1) { |t,(pr,po)| t * (pr**po) } }.
sort
end
返回的数组包括1
和n
(n
的因子)。如果应排除这些值,请将.sort
替换为.sort - [1, n]
。
<强>实施例强>
get_factors(24)
#=> [1, 2, 3, 4, 6, 8, 12, 24]
get_factors(64)
#=> [1, 2, 4, 8, 16, 32, 64]
get_factors(90)
#=> [1, 2, 3, 5, 6, 9, 10, 15, 18, 30, 45, 90]
<强>解释强>
考虑
n = 60
步骤如下。
a = Prime.prime_division(30)
#=> [[2, 2], [3, 1], [5, 1]]
Ergo,30
的素数为2
,3
和5
,以及
60 = 2**2 * 3**1 * 5**1
primes, nbr = a.transpose
#=> [[2, 3, 5], [2, 1, 1]]
primes
#=> [2, 3, 5]
nbr
#=> [2, 1, 1]
powers = nbr.map { |m| (0..m).to_a }
#=> [[0, 1, 2], [0, 1], [0, 1]]
这意味着每个因素都是0
,1
或2
2
,0
或1
{的乘积{1}}和3
或0
1
。
5
现在考虑b = powers.shift
#=> [0, 1, 2]
powers
#=> [[0, 1], [0, 1]]
c = b.product(*powers)
#=> [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1],
# [1, 1, 0], [1, 1, 1], [2, 0, 0], [2, 0, 1], [2, 1, 0], [2, 1, 1]]
d = c.map { |pows| primes.zip(pows).reduce(1) { |t,(pr,po)| t * (pr**po) } }
#=> [1, 5, 3, 15, 2, 10, 6, 30, 4, 20, 12, 60]
d.sort
#=> [1, 5, 3, 15, 2, 10, 6, 30, 4, 20, 12, 60]
的计算。传递给块的d
的第10个元素是c
。该元素的块计算如下。
[2, 0, 1]
pows = [2, 0, 1]
e = primes.zip(pows)
#=> [[2, 2], [3, 0], [5, 1]]
e.reduce(1) { |t,(pr,po)| t * (pr**po) }
#=> 20
计算相当于
reduce
传递给块的2**2 * 3**0 * 5**1
#=> 4 * 1 * 5 => 20
的其他值的计算是相似的。
答案 3 :(得分:0)
一种简单的方法是用
替换方法的最后一行factors.map(&:sort).uniq
对所有子阵列进行排序,然后消除重复。