Yuk*_*ita 7 python algorithm math
我必须将数字列表分为两组,以便一组中没有数字的因数也等于第二组中任何数字的因数。我认为我们只需要找出分组,使得每个分组中数字乘积的GCD为1。例如,
如果我们有列表2,3,4,5,6,7,9,则可能的组为-
(2,3,4,6,9)(5,7)(2,3,4,5,6,9)(7)(2,3,4,6,7,9)(5)
我最初想做的是-
在前面的示例中,算法看起来像这样-
我认为该算法有效,但是是解决此问题的非常不好的方法。我可以将素数硬编码为一个大数,然后找到最接近我的最大数的素数,这可能会使其更快,但是如果元素的数量约为10E6或更多,它仍然涉及过多的除法。我在想也许有更好的方法来解决这个问题。也许我缺少一些数学公式,或者一些可以减少迭代次数的小逻辑。
我的问题是关于算法的,因此伪代码也可以使用,我不需要完成的代码。但是,我对Python,Fortran,C,BASH和Octave感到很满意,因此使用这些语言的答案也将有所帮助,但是正如我所说的,语言并不是这里的重点。
而且我想我可能不了解一些可能会使我的问题变得更好的术语,因此也希望对重新措词有所帮助。
tl; dr:使用素数筛子获取素数列表,使用不相交集存储和组合组
您走在正确的轨道上。您可以使用Erasthones的Sieve来获取质数列表,并且只需要~O(n log n)时间和内存即可进行质因数分解,这还不错。
让我们重新构造问题的后半部分:
现在,您的问题是找到两个不相交的节点组。将这些组存储在不相交的集中。
示例的简短版本,带有elements [2,3,4,5,6]。让我们在“子集”列中跟踪每组节点,并遍历上面的数组。
| iteration | subsets | subset1 | description |
|-----------|-----------------|---------|-------------------------------------------------------------------------------------------------------------------------|
| start | [] | n/a | |
| 1 | [] | {2} | add a new subset, 2 |
| 2 | [{2}] | {3} | 3 shares no common factors with 2, so create a new subset 2 |
| 3 | [{2},{3}] | {4} | 4 shares a common factor with 2, but not with 3, so merge it with {2} |
| 4 | [{2,4},{3}] | {5} | 5 shares no common factors with 2,3 or 4, so create a new subset |
| 5 | [{2,4},{3},{5}] | {6} | 6 shares a common factor with {2,4}, so merge it into that. it also shares a common factor with {3}, so merge that too |
| 6 | [{2,4,3,6},{5}] | | done |
Run Code Online (Sandbox Code Playgroud)
用分离集与标准特性开始make_set,union和find方法如维基百科上所述。
get_prime_factors返回set该子集元素的主要因子的Python 以提高空间效率,只有父节点应包含此属性def get_prime_factors(x):
return Find(x)._prime_factors
Run Code Online (Sandbox Code Playgroud)
union以返回对新创建集合的引用,并跟踪主要因子(集合交集)def union(x, y):
# use Wikpidia's code
# ...
# add this:
xRoot._prime_factors |= yRoot._prime_factors
return xRoot
Run Code Online (Sandbox Code Playgroud)
get_subsets(),一种迭代子集的方式。天真的方法是遍历原始数组并find在每个数组上运行。较不幼稚的方法是跟踪另一组父母,但这种选择不会影响最坏情况下的运行时间。disjoint_set = AugmentedDisjointSet([])
elems = [2,3,6,5,4]
for new_number in elems:
subset1 = disjoint_set.make_set(new_number)
for subset2 in disjoint_set.get_subsets():
if (subset1.get_prime_factors() & subset2.get_prime_factors()): # merge if the subsets share a common factor
subset1 = disjoint_set.union(subset1, subset2)
# show result. this may give between 1 (all numbers share a common factor)
# and infinite subsets (all numbers are relatively prime)
# for your example, this will return something like {2,3,4,6,9}, {5}, {7}
# you can group them however you'd like to.
print('result': disjoint_set.get_subsets())
Run Code Online (Sandbox Code Playgroud)
最坏的情况是O(n^2*a(n))时间运行a(n),如果每个元素都相对质数,则逆阿克曼函数在哪里(即很小)在哪里,并且还有O(n)空间。
| 归档时间: |
|
| 查看次数: |
443 次 |
| 最近记录: |