Учитывая несортированный массив, найдите максимальное вычитание между двумя элементами в массиве

Я получил этот вопрос из интервью в Microsoft: учитывая несортированный массив, найти максимальное вычитание между двумя элементами в массиве можно следующим образом:

(Index1, Index2) = arr[Index2] - arr[Index1].    Index1<Index2.

Пример:

given the array: [1, 5, 3, 2, 7, 9, 4, 3] -> Output: (1,9)=8.
given the array: [4, 9, 2, 3, 6, 3, 8, 1] -> Output: (2,8)=6.

Наивное решение работает за O(n^2) раз: отсканируйте первый индекс для вычитания со всеми другими индексами и сохраните максимальное значение, перейдите к следующему индексу и так далее.

Есть ли способ оптимизировать это?

2 ответа

Решение

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

[1, 5, 3, 2, 7, 9, 4, 3]
=>
[9, 9, 9, 9, 9, 4, 3]

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

Реализация на питоне:

def find_max(xs):
    ys = []
    cur_max = float('-inf')
    for x in reversed(xs):
        cur_max = max(x, cur_max)
        ys.append(cur_max)
    ys = ys[::-1][1:]
    return max(y - x for x, y in zip(xs, ys))

Мы также можем лениво построить массив максимумов, что дает нам O(1) память, которая является лучшей из возможных:

def find_max(xs):
    cur_max = float('-inf')
    cum_max = xs[-1]
    for i in range(len(xs) - 2, -1, -1):
        cur_max = max(cur_max, cum_max - xs[i])
        cum_max = max(cum_max, xs[i])
    return cur_max

Я думаю, что это правильно, и O(nlogn): разделить в середине и выбрать справа максимум, слева значение min. Также разделите остальные 2 квартала, если один из них даст больший результат, продолжайте рекурсивно.

Второй пример:

4, 9, 2, 3| 6, 3, 8, 1 -> 2 and 8
4, 9| 2, 3, 6, 3, 8, 1 -> 4 and 8
4, 9, 2, 3, 6, 3| 8, 1 -> 2 and 8

Итак, работа над правильным разделением:

4, 9, 2, 3, 6, 3, 8| 1 -> 2 and 1

Выбор 2 а также 8 вариант. Это также работает для первого примера.

Другие вопросы по тегам