2017-02-20 4 views
0

Этот метод пытается выразить num как произведение элементов в обр.Big O Сложность алгоритма

Для например method1 (37, [1,3,5]) возвращает [2,0,7]

// arr is an array of divisors sorted in asc order, e.g. [1,3,5] 
def method1(num, arr) 
    newArr = Array.new(arr.size, 0) 
    count = arr.size - 1 

    while num > 0 
    div = arr[count] 

    if div <= num 
     arr[count] = num/div 
     num = num % div 
    end 

    count = count - 1 
    end 

    return newArr 
end 

бы очень признателен, если вы могли бы дать мне некоторую помощь, чтобы получить сложность алгоритма , Пожалуйста, не стесняйтесь, чтобы улучшить эффективность моего алгоритма

+0

Где инициализируется счет? – Scovetta

+0

Эмпирическое правило для определения нотации Big-O: если вы удваиваете размер ввода, то сколько еще нужно выполнить алгоритму: (a) Если он делает точно такой же ввод, это, вероятно, O (1). (b) Если он дважды вводит вход, это, вероятно, O (n). (c) Если он в четыре раза превышает вход, это, вероятно, O (n^2). – Scovetta

+0

О, забыл включить счет здесь. Спасибо –

ответ

0

Вот что вы можете сделать:

def method1(num, arr) 

    newArr = Array.new(arr.size, 0) 
    count = arr.size()-1 

    while num>0 
     div = arr[count] 

     if div <= num 
      arr[count] = num/div 
      num = num % div 
     end 

     count = count + 1 
    end 
    return arr 
end 


ar = Array.new(25000000) { rand(1...10000) } 

t1 = Time.now 
method1(37, ar) 
t2 = Time.now 

tdelta = t2 - t1 

print tdelta.to_f 

Выход:

0.102611062 

Теперь двойной размер массива:

ar = Array.new(50000000) { rand(1...10) } 

Выход:

0.325793964 

И снова дважды:

ar = Array.new(100000000) { rand(1...10) } 

Выход:

0.973402568 

так что n двойники, длительность примерно в три раза. Поскольку O (3n) == O (n), весь алгоритм работает в O (n) времени, где n представляет размер входного массива .

+0

Я вижу, это очень полезно! Большое вам спасибо за вашу помощь! –

+0

'O (3n)' должно быть 'O (1.5n)', но это 'O (n)' в любом случае. –

1

Вот рефакторинга версия коды:

def find_linear_combination(num, divisors) 
    results = divisors.map do |divisor| 
    q, num = num.divmod(divisor) 
    q 
    end 
    results if num == 0 
end 

puts find_linear_combination(37, [5, 3, 1]) == [7, 0, 2] 
puts find_linear_combination(37, [1, 3, 5]) == [37, 0, 0] 
puts find_linear_combination(37, [5]).nil? 

С n быть размером divisors, этот алгоритм ясно, как представляется, O(n). Есть только один цикл (map), и внутри цикла есть только одно целочисленное деление.

Обратите внимание, что делители должны быть записаны в порядке убывания. Если линейная комбинация не найдена, метод возвращает nil.

Если вы хотите отсортировать divisors, алгоритм будет O(n*log n). Также неплохо было бы добавить 1 (O(1)).

+0

Спасибо за ответ!Дивизоры - это не проблема, поскольку он может считаться уже отсортированным в порядке возрастания –

Смежные вопросы