2015-06-07 3 views
2

Вам предоставляется массив с n элементами: d[0], d[1], ..., d[n-1]. Рассчитайте сумму (S) всей разности max каждого смежного субмарины.оптимальный способ найти сумму (S) всей разности максимальных смежных смежных поддиапазонов

Формально: S = сумма {тах {д [л, ..., г]} - {мин д [л, ..., г}}, ∀ 0 = < < л = г < п

Входной сигнал:

4 
1 3 2 4 

Выход:

12 

Пояснение:

л = 0; r = 0; массив: [1] sum = max ([1]) - min ([1]) = 0

l = 0; r = 1; массив: [1,3] sum = max ([1,3]) - min ([1,3]) = 3 - 1 = 2

l = 0; r = 2; массив: [1,3,2] sum = max ([1,3,2]) - min ([1,3,2]) = 3 - 1 = 2

l = 0; r = 3 ; массив: [1,3,2,4] sum = max ([1,3,2,4]) - мин ([1,3,2,4]) = 4 - 1 = 3

l = 1; r = 1 приведет к нулю

l = 1; r = 2; array: [3,2] sum = max ([3,2]) - min ([3,2]) = 3 - 2 = 1;

l = 1; r = 3; массив: [3,2,4] sum = max ([3,2,4]) - мин ([3,2,4]) = 4 - 2 = 2;

l = 2; r = 2; приведет к нулю

l = 2; r = 3; массив: [2,4] sum = max ([2,4]) - мин ([2,4]) = 4 -2 = 2;

l = 3; r = 3 приведет к нулю;

Общая сумма = 12

Моих мыслей: Грубой проверка силы для все возможного подмножества; контагиозный массив.

How to optimize it for larger number? 

ответ

1

Предположим, у вас есть последовательность длины п, и вы хотите, чтобы вычислить минимум (или максимум) скользящего окна некоторого фиксированного размера м < п. Затем (неожиданно), this can be done in O(n) time.

Итак, теперь для размеров окна m = 1, ..., n вам необходимо запустить скользящее окно слева направо; для каждого слайда окна вам просто нужно добавить max-min элементов внутри окна.При этом время работы составляет Theta (n^2). Это улучшает ваш наивный алгоритм, который равен Theta (n^3).

+0

Он может найти min и max в O (1). когда «n» и «r» равны, установите min = max = arr [l], затем, добавив следующий элемент, сравните его с min и max и при необходимости измените их. – splash58

+0

@ splash58 Он может найти min и max of что в O (1)? Все прогоны определенного размера для скользящего окна? Вся проблема? Не стесняйтесь писать альтернативное решение. Я не уверен, что комментарии - это способ объяснить это. –

+0

Я уже писал, что нет необходимости вычислять max и min. Я думаю, что это уменьшает временную оценку – splash58

1

Это можно сделать в линейном режиме! Каждый элемент переходит в сумму один раз для каждого подмассива, который является максимальным, и каждый элемент вычитается один раз для каждого подмассива, это минимум. Нам нужен алгоритм с линейным временем для определения количества подмассивов, каждый из которых является максимальным или минимальным, и мы можем сделать это с незначительной модификацией алгоритма all nearest smaller values.

Идея состоит в том, чтобы найти, сколько подмассивов является элементом max, мы сохраняем стек элементов, которые мы видели, которые больше всех последующих элементов, которые мы видели, вместе с позициями этих чисел , Когда мы находим элемент, который больше, чем последний элемент в стеке, мы знаем, как далеко может быть Subarray слева или справа от элемента в верхней части стека и по-прежнему иметь максимальный размер, и мы можем использовать его для определить, сколько подмассивов - это максимум. Мы можем справиться с минимумами, просто отрицая все элементы массива.

def max_sums(d): 
    stack = [(-1, float('inf'))] 
    sum_ = 0 
    for i, x in enumerate(d): 
     while x > stack[-1][1]: 
      prev_i, prev_x = stack.pop() 
      prev_prev_i, prev_prev_x = stack[-1] 
      sum_ += prev_x * (i - prev_i) * (prev_i - prev_prev_i) 
     stack.append((i, x)) 
    while len(stack) > 1: 
     prev_i, prev_x = stack.pop() 
     prev_prev_i, prev_prev_x = stack[-1] 
     sum_ += prev_x * (len(d) - prev_i) * (prev_i - prev_prev_i) 
    return sum_ 

def max_differences_sum(d): 
    return max_sums(d) + max_sums([-x for x in d]) 

Вот пример запуска алгоритма. Предположим, что вход [30, 10, 40, 20]. Затем вычислить сумму Maxes всех подрешеток, мы перебирать вход следующим образом:

30 

Нажимает пару (0, 30) в стек. Теперь стек записывает, что мы увидели 30 с индексом 0.

10 

30 > 10, поэтому мы помещаем пару (1, 10) в стек. Теперь стек записи, которые мы увидели 10 с индексом 1.

40 

10 < 40, так подмассивом с макс 10 не может включать этот элемент. Мы видим, что Subarray с max 10 должен начинаться после индекса 30 и заканчиваться до индекса 40, поэтому он имеет 1 возможную левую конечную точку и 1 возможную правую конечную точку, и есть 1*1 такой массив. Добавим 10*1*1 к сумме и вытащите (1, 10) из стека. Сумма составляет 10.

30 < 40, поэтому подмассив с max 30 также не может включать этот элемент. Мы видим, что подмассив с max 30 должен начинать индексом 0 и заканчиваться либо с индексом 0, либо с индексом 1, поэтому здесь есть 1*2 таких массивов. Добавим 30*1*2 к сумме и напишите (0, 30). Сумма составляет 70.

Стек теперь пуст, поэтому мы нажимаем (2, 40).

20 

40 > 20, поэтому мы помещаем (3, 20).

Мы итерация всех входные, так и для любой пары (i, x) еще на массиве, подмассив с максимальным x может закончиться в любом из индекса i до конца массива, и он может начать в любом месте от i к предыдущему индекс стека (или начало массива, если нет предыдущей записи).

(3, 20) находится в стеке с (2, 40) под ним, так подмассивом с макс 20 должен начинаться и заканчиваться на индекс 3. Добавим 20*1*1 к сумме и поп (3, 20). Сумма теперь равна 90.

(2, 40) находится в стеке ни с чем под ним, так подмассивом с макс 40 может начаться в любом индексе < = 2 и заканчивается в любом индексе> = 2. Добавим 40*3*2 к сумме и опустошить стек. Сумма составляет 330.

Мы учли все положительные условия в сумме. Чтобы вычесть минимальные значения, мы отменяем все входные элементы и снова загружаем их по вышеописанному алгоритму. В итоге мы вычитаем 170, для общей суммы 160.

+0

вы не учитывали минимальный размер массива. Нам нужно найти разницу между max-min каждого вспомогательного массива. И код действительно трудно понять. Будет хорошо, если вы прокомментируете это, что вы пытаетесь сделать, и укажите пример работы вашего алгоритма. Спасибо – Cyclotron3x3

+0

@ Cyclotron3x3: он рассматривает минимальные значения; это то, что делает 'max_sums ([- x for x in d])'. – user2357112

+0

жаль беспокоить вас больше, можете ли вы привести пример работы вашего алгоритма. Его трудно понять ваш код на Python. (Я java :)) ... спасибо – Cyclotron3x3

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