时间复杂度可以从O(n ^ 2)降低到O(n)吗?

时间:2019-10-07 11:42:59

标签: python time-complexity

我有一个序列A 1 ,A 2 ,A 3 ..... A N 。对于每个有效的i,元素A i count value是有效索引j < i的数量,使得A j 为可被A i 整除。

我想知道最大的count value

我使用以下代码完成了此操作:

for _ in range(int(input())):             #number of test cases
    n = int(input())                      # no. of elements in A  
    A = list(map(int, input().split()))
    count_arr = []                      # array with count value
    for i in range(n):
        b = A[:i]
        b = [x%A[i] for x in b]
        count_arr.append(b.count(0))
    print(max(count_arr))

  

样本输入:

1
7 
8 1 28 4 2 6 7
     

样本输出:

3
     

说明:

     

A 5 = 2除以4、28和8,因此其计数值为3。   是count_arr中没有更高计数值的元素。

时间复杂度为O(n 2 )。我想知道是否可以以O(n)复杂度更快地解决此问题。

1 个答案:

答案 0 :(得分:1)

如果您有一种简便的方法来找出数字的除数,则只需遍历一次序列:

def divisors(num):
    yield 1

    for i in range (2, int(num ** .5) + 1):
        if num % i: # not divisible
            continue 
        yield i
        if i**2 != num:
            yield num // i

查找数字除数是一种相当幼稚的方法。

如果还需要包含原始编号,则可以将divisors更改为

def divisors(num):
    yield 1
    if num == 1:
        return
    yield num
    for i in range (2, int(num ** .5) + 1):
        if num % i: # not divisible
            continue 
        yield i
        if i**2 != num:
            yield num // i

然后,您需要一个结构来保存每个除数已经显示了多少时间。为此,collections.Counter很理想

def previous_multiples(sequence):
    counter = Counter()
    for i in sequence:
        yield counter[i]
        counter.update(divisors(i))

每个数字的收益率是先前数字可被其整除的数量。然后用自己的除数更新除数

可以这样称呼max(previous_multiples(sequence))

这是在找到每个数字的除数与检查每个元素与所有先前元素所花费的时间之间进行权衡。