从给定范围中删除给定数字集的所有倍数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从给定范围中删除给定数字集的所有倍数相关的知识,希望对你有一定的参考价值。
我坚持一个问题,它说,给出一个数字N
和一组数字,S = {s1,s2,.....sn}
其中s1 < s2 < sn < N
,从{s1, s2,....sn}
范围中删除1..N
的所有倍数
例:
Let N = 10
S = {2,4,5}
Output: {1, 7, 9}
Explanation: multiples of 2 within range: 2, 4, 6, 8
multiples of 4 within range: 4, 8
multiples of 5 within range: 5, 10
我想有一个算法方法,伪代码而不是完整的解决方案。
我尝试过的:
(Considering the same example as above)
1. For the given N, find all the prime factors of that number.
Therefore, for 10, prime-factors are: 2,3,5,7
In the given set, S = {2,4,5}, the prime-factors missing from
{2,3,5,7} are {3,7}.
2. First, check prime-factors that are present: {2,5}
Hence, all the multiples of them will be removed
{2,4,5,6,8,10}
3. Check for non-prime numbers in S = {4}
4. Check, if any divisor of these numbers has already been
previously processed.
> In this case, 2 is already processed.
> Hence no need to process 4, as all the multiples of 4
would have been implicitly checked by the previous
divisor.
If not,
> Remove all the multiples from this range.
5. Repeat for all the remaining non primes in the set.
请提出您的想法!
可以使用类似于Eratosthenes筛子的东西在O(N log(n))时间和O(N)额外内存中解决它。
isMultiple[1..N] = false
for each s in S:
t = s
while t <= N:
isMultiple[t] = true
t += s
for i in 1..N:
if not isMultiple[i]:
print i
这使用O(N)内存来存储isMultiple
数组。
时间复杂度为O(N log(n))。实际上,对于S中的第一个元素,内部while循环将执行N / s1次,然后对于第二个元素执行N / s2,依此类推。
我们需要估计N / s1 + N / s2 + ... + N / sn的大小。
N / s1 + N / s2 + ... + N / sn = N *(1 / s1 + 1 / s2 + ... + 1 / sn)<= N *(1/1 + 1/2 + .. 。+ 1 / n)。
最后的不等式是由于s1 <s2 <... <sn的事实,因此最坏的情况是它们取值{1,2,... n}。
然而,谐波系列1/1 + 1/2 + ... + 1 / n在O(log(n))中,(例如参见this),因此上述算法的时间复杂度为O(N log( N))。
基本解决方案
let set X be our output set.
for each number, n, between 1 and N:
for each number, s, in set S:
if s divides n:
stop searching S, and move onto the next number,n.
else if s is the last element in S:
add n to the set X.
你可以在运行这个算法之前显然删除S中的倍数,但我不认为素数是可行的
由于S被排序,我们可以通过跳过已标记的S(O(N)
)中的元素来保证http://codepad.org/Joflhb7x的复杂性:
N = 10
S = [2,4,5]
marked = set()
i = 0
curr = 1
while curr <= N:
while curr < S[i]:
print curr
curr = curr + 1
if not S[i] in marked:
mult = S[i]
while mult <= N:
marked.add(mult)
mult = mult + S[i]
i = i + 1
curr = curr + 1
if i == len(S):
while curr <= N:
if curr not in marked:
print curr
curr = curr + 1
print list(marked)
以上是关于从给定范围中删除给定数字集的所有倍数的主要内容,如果未能解决你的问题,请参考以下文章
找出能被两个给定参数和它们之间的连续数字整除的最小公倍数。 范围是两个数字构成的数组,两个数字不一定按数字顺序排序。
2022-08-06:给定一个数组arr,长度为N,arr中所有的值都在1~K范围上, 你可以删除数字,目的是让arr的最长递增子序列长度小于K。 返回至少删除几个数字能达到目的。 N <= 10^4
GeoDjango 获取到给定位置集的任何点的给定距离内的模型的所有记录