【问题标题】:Remove all the multiples of a given set of numbers from given range从给定范围内删除给定数字集的所有倍数
【发布时间】:2017-12-23 05:50:31
【问题描述】:

我遇到了一个问题,它说,给定一个数字N 和一组数字S = {s1,s2,.....sn} 其中s1 < s2 < sn < N,从1..N 范围内删除{s1, s2,....sn} 的所有倍数

示例:

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.

请提出你的想法!

【问题讨论】:

    标签: algorithm data-structures numbers


    【解决方案1】:

    使用类似于埃拉托色尼筛法的方法可以在 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))。实际上,内部的 while 循环将对 S 中的第一个元素执行 N / s1 次,然后对第二个元素执行 N / s2 次,依此类推。

    我们需要估计N / s1 + N / s2 + ... + N / sn的大小。

    N / s1 + N / s2 + ... + N / sn = N * (1/s1 + 1/s2 + ... + 1/sn)

    最后一个不等式是由于 s12 n,因此最坏的情况是它们取值 {1, 2, .. n}。

    然而,谐波级数 1/1 + 1/2 + ... + 1/n 在 O(log(n)) 中,(例如参见this),因此上述算法的时间复杂度是O(N log(n))。

    【讨论】:

      【解决方案2】:

      基本解决方案:

      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 中的倍数,但我不认为素数是要走的路

      【讨论】:

        【解决方案3】:

        由于 S 已排序,我们可以通过跳过 S 中已标记 (http://codepad.org/Joflhb7x) 中的元素来保证O(N) 的复杂性:

        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)
        

        【讨论】:

          猜你喜欢
          • 2019-06-25
          • 2015-07-28
          • 1970-01-01
          • 2016-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多