Самый высокий процент увеличения

Допустим, у нас есть следующий набор чисел, представляющих значения с течением времени.

1 2 3 10 1 20 40 60

Теперь я ищу алгоритм, чтобы найти самый высокий процент увеличения от одного раза к другому. В приведенном выше случае ответом будет пара (1, 60), которая имеет увеличение на 6000%.

На данный момент лучший алгоритм, который я могу придумать, — это метод грубой силы. Мы рассматриваем все возможные пары, используя серию итераций:

1-я итерация:

1-2 1-3 1-10 .. 1-60

2-я итерация

 2-3 2-10 2-1 ... 2-60

(и т.д.)

Это имеет сложность O(n3).

Я также думал о другом подходе. Найдите все строго возрастающие последовательности и определите процентное увеличение только этих строго возрастающих последовательностей.

Какая-нибудь другая идея пришла вам в голову, ребята? Пожалуйста, поправьте меня, если мои идеи неверны!


person Karthick    schedule 05.02.2011    source источник
comment
Можете ли вы уточнить термин «процентное увеличение»? Это finalValue/initialValue?   -  person Nikita Rybak    schedule 05.02.2011
comment
Считайте, что эти числа представляют собой объем производства компании за период в 8 лет (с 2000 по 2008 год), т. е. объем производства (2000 г.) = 1, объем производства (2001 г.) = 2 .. объем производства (2008 г.) = 60; Таким образом, цель здесь состоит в том, чтобы найти период времени, в котором наблюдалось наибольшее увеличение процента производства. Это может быть период с 2000 по 2001 год, или с 2001 по 2003 год, или даже с 2000 по 2003 год! Вам нужны дополнительные разъяснения?   -  person Karthick    schedule 05.02.2011
comment
Каковы ваши пределы? Вы можете улучшить временную сложность до O(n) , если разрешите пространственную сложность O(n)   -  person Foo Bah    schedule 05.02.2011
comment
Никаких ограничений... Единственная гарантия, которую я могу вам дать, это то, что значения будут положительными!   -  person Karthick    schedule 05.02.2011
comment
Есть решение для динамического программирования   -  person Foo Bah    schedule 05.02.2011
comment
gr8 .. не могли бы вы объяснить мне больше?   -  person Karthick    schedule 05.02.2011
comment
Метод грубой силы имеет O (n ^ 2), а не n ^ 3.   -  person apadana    schedule 15.11.2014


Ответы (4)


Возможно, я неправильно понял проблему, но кажется, что все, что вам нужно, это наибольшее и наименьшее числа, так как это два числа, которые имеют значение.

while true:
    indexOfMax = max(list)
    indexOfMin = min(list)
    list.remove(indexOfMax)
    list.remove(indexOfMin)
    if(indexOfmax < indexOfMin)
        contine
    else if(indexOfMax == indexOfMin)
        return -1
    else
        SUCCESS
person Novikov    schedule 05.02.2011
comment
Это неправильный ответ. Пусть у нас есть 10, 12, 8, 10, 5, 11. Понятно, что между 5 и 11 у нас прирост более 50%. Но в вашем решении мы выбрасываем 5 и 12 на самой первой итерации и не будем найти правильный ответ. Думаю, будет полезно keithschwarz.com/interesting/code/?dir= прибыль от одной продажи - person Paval; 23.10.2015

Насколько я понимаю (вы меня не поправили в своем комментарии), вы хотите максимизировать a[i]/a[j] для всех j <= i. Если это правильно, то для каждого i нам нужно знать только наименьшее значение перед ним.

int current_min = INFINITY;
double max_increase = 0;
for (int i = 0; i < n; ++i) {
    current_min = min(current_min, a[i]);
    max_increase = max(max_increase, a[i] / min);
}
person Nikita Rybak    schedule 05.02.2011
comment
Хорошо.. давайте предположим, что это так.. Нанесите этот подсчет производства на график.. Теперь вы можете найти пики и уменьшающиеся периоды после пика... Итак, если пик 1: 1-2 пик2-5-6.. Итак, процентное увеличение в Peek 1 больше, чем в Peek 2 .. понял? - person Karthick; 05.02.2011
comment
@Картик Нет. Я понятия не имею, что ты пытаешься сделать. - person Nikita Rybak; 05.02.2011

Итак, вы просто хотите сравнить каждое число попарно и посмотреть, какая пара имеет наибольшее отношение второго числа к первому числу? Просто повторение с двумя циклами (один с i = от 0 до n и внутренний цикл с j = i + 1 до n) даст вам O (n ^ 2). Я предполагаю, что это на самом деле ваше оригинальное решение, но вы неправильно сказали, что сложность была O (n ^ 3). Это n^2.

Однако вы можете добраться до O (n log n). Возьмите свой список, превратите его в список, где каждый элемент представляет собой пару (индекс, значение). Затем отсортируйте его по второму элементу пары. Затем добавьте два указателя в список, один слева (от 0 до n-1), а другой справа (от n-1 до 0). Найдите первую пару элементов, у которой исходный индекс левого элемента меньше исходного индекса правого элемента. Сделанный.

1 2 3 10 1 20 40 60
becomes
(1,0) (2,1) (3,2) (10,3) (1, 4) (20, 5) (40, 6) (60,7)
becomes
(1,0) (1,4) (2,1) (3,2) (10,3) (20,5) (40,6) (60,7)

Итак, ваш ответ 60/1, от индекса 0 до индекса 7.

Если это не то, что вы ищете, было бы полезно, если бы вы сказали, какой правильный ответ был для ваших примеров чисел.

person nsanch    schedule 06.02.2011

Если я правильно понимаю вашу проблему, вы ищете два индекса (i, j) в массиве с i ‹ j, который имеет наибольшее отношение A[j]/A[i]. Если это так, вы можете уменьшить это до этой связанной проблемы< /strong>, который просит вас найти индексы (i, j) с ij таким образом, чтобы A[j] - A[i] было как можно больше. Эта задача имеет очень быстрый O(n)-временной и O(1)-пространственный алгоритм, который также можно адаптировать к этой задаче. Интуиция состоит в том, чтобы решить задачу для массива, состоящего только из первого элемента вашего массива, затем для первых двух элементов, затем для первых трех и т. д. Как только вы решили задачу для первых n элементов массива, у вас есть общее решение проблемы.

Давайте подумаем, как это сделать. Первоначально, когда вы рассматриваете только первый элемент массива, лучшее процентное увеличение, которое вы можете получить, составляет 0%, сравнивая элемент с самим собой. Теперь предположим (индуктивно), что вы решили задачу для первых k элементов массива и хотите посмотреть, что произойдет, когда вы посмотрите на следующий элемент массива. Когда это происходит, выполняется одно из двух условий. Во-первых, максимальное процентное увеличение первых k элементов также может быть максимальным процентным увеличением первых (k + 1) элементов. Например, если (k+1)st элемент массива является очень маленьким числом, то, скорее всего, вы не сможете получить большое процентное увеличение от чего-то в первых k элементах до этого значения. Во-вторых, максимальное процентное увеличение может быть от одного из первых k элементов до (k + 1)-го элемента. Если это так, наибольшее процентное увеличение будет от наименьшего из первых k элементов до (k + 1)-го элемента.

Объединяя эти два случая, мы получаем, что наилучшее процентное увеличение первых k + 1 элементов равно максимуму

  • Наибольшее процентное увеличение первых k элементов или
  • Процентное увеличение от наименьшего из первых k элементов до (k + 1)-го элемента.

Вы можете реализовать это, перебирая элементы массива, отслеживая два значения — минимальное значение, которое вы видели до сих пор, и пару, которая максимизирует процентное увеличение. Например, для исходного примера массива

1  2  3  10  1  20  40  60

Алгоритм будет работать следующим образом:

       1       2       3       10        1       20       40        60
min        1       1        1       1       1         1        1        1
best     (1,1)   (1, 2)  (1, 3)  (1, 10)  (1, 10)  (1, 20)   (1, 40)  (1, 60)

и вы должны вывести (1, 60) как самый высокий процент увеличения. В другом массиве, например, в этом:

3   1   4   2   5

тогда алгоритм будет выглядеть следующим образом: 3 1 4 2 5 мин 3 1 1 1 1 лучший (3,3) (3,3) (1,4) (1,4) (1,5)

и вы бы вывели (1, 5).

Весь этот алгоритм использует только пространство O(1) и выполняется за время O(n), что является чрезвычайно хорошим решением проблемы.

В качестве альтернативы вы можете подумать о том, чтобы свести эту проблему непосредственно к задаче о максимальной прибыли от одной продажи, взяв логарифм всех значений в вашем массиве. В этом случае, если вы найдете пару значений, где log A[j] - log A[i] максимизируется, это эквивалентно (используя свойства логарифмов) нахождению пары значений, где log (A[j] / A [i]) максимизируется. Поскольку логарифмическая функция монотонно возрастает, это означает, что вы нашли пару значений, где A[j] / A[i] максимальны, как и предполагалось.

person templatetypedef    schedule 30.08.2011