Действительно ли возможно найти два числа, различие которых минимально в O (n) время

Довольно скрытая функция - то, что можно определить переменные в, если условие и его объем еще охватят только по если, и блоки:

if(int * p = getPointer()) {
    // do something
}

Некоторое использование макросов, что, например, для обеспечения некоторого "заблокированного" объема как это:

struct MutexLocker { 
    MutexLocker(Mutex&);
    ~MutexLocker(); 
    operator bool() const { return false; } 
private:
    Mutex &m;
};

#define locked(mutex) if(MutexLocker const& lock = MutexLocker(mutex)) {} else 

void someCriticalPath() {
    locked(myLocker) { /* ... */ }
}

Также BOOST_FOREACH использует его под капотом. Для завершения этого это не только возможно в если, но также и в переключателе:

switch(int value = getIt()) {
    // ...
}

и в некоторое время цикле:

while(SomeThing t = getSomeThing()) {
    // ...
}

(и также в для условия). Но я не слишком уверен, являются ли они всем этим полезным:)

23
задан Johan - reinstate Monica 24 September 2011 в 22:31
поделиться

8 ответов

Найдите самый маленький и самый большой элемент в списке. Разница наименьшая-наибольшая будет минимальной.

Если вы ищете неотрицательную разницу, тогда это, конечно, по крайней мере так же сложно, как проверить, есть ли в массиве два одинаковых элемента. Это называется проблемой уникальности элементов , и без каких-либо дополнительных предположений (например, ограничение размера целых чисел, допускающих другие операции, кроме сравнения) требуется> = n log n времени. Это одномерный случай поиска ближайшей пары точек .

22
ответ дан 29 November 2019 в 02:27
поделиться

Я думаю, что это возможно. Секрет в том, что на самом деле вам не нужно сортировать список, вам просто нужно создать список существующих чисел. Это может считаться "предположением" с алгоритмической точки зрения, но не с практической точки зрения. Мы знаем, что целые числа ограничены минимальным и максимальным значением.

Итак, создайте массив из 2-битных элементов, по 1 паре для каждого целого числа от INT_MIN до INT_MAX включительно, установите для всех их значение 00.

Итерируйте через весь список номеров. Для каждого числа в списке, если соответствующие 2 бита равны 00, установите их на 01. Если они 01, установите их на 10. В противном случае игнорируйте. Очевидно, это O (n).

Затем, если какой-либо из двух битов установлен в 10, это ваш ответ. Минимальное расстояние равно 0, потому что список содержит повторяющееся число. Если не, Просмотрите список и найдите минимальное расстояние. Многие люди уже указали, что для этого существуют простые алгоритмы O (n).

Итак, O (n) + O (n) = O (n).

Изменить: отвечать на комментарии.

Интересные моменты . Я думаю, что вы могли бы достичь тех же результатов, не делая никаких предположений, сначала найдя min / max списка и используя разреженный массив от min до max для хранения данных. Учитывает предположение INT_MIN / MAX, пространственную сложность и временную сложность O (m) сканирования массива.

Я думаю, что вы могли бы достичь тех же результатов, не делая никаких предположений, сначала найдя минимальное / максимальное значение списка и используя разреженный массив в диапазоне от min до max для хранения данных. Учитывает предположение INT_MIN / MAX, пространственную сложность и временную сложность O (m) сканирования массива.

Я думаю, что вы могли бы достичь тех же результатов, не делая никаких предположений, сначала найдя min / max списка и используя разреженный массив от min до max для хранения данных. Учитывает предположение INT_MIN / MAX, пространственную сложность и временную сложность O (m) сканирования массива.

2
ответ дан 29 November 2019 в 02:27
поделиться

Лучшее, что я могу придумать, - это отсортировать массив (возможно, комбинируя равные значения), а затем выполнить отсортированные сравнения - сортировка по ячейкам равна O (n + M ) (M - количество различных значений). Однако это требует больших объемов памяти. Некоторая форма сортировки по ведру или основанию системы счисления будет промежуточной по времени и более эффективной в пространстве.

1
ответ дан 29 November 2019 в 02:27
поделиться

Отсортируйте список с помощью radixsort (т.е. O (n) для целых чисел), затем итерация и отслеживание наименьшего расстояния до сих пор.

(Я предполагаю, что ваше целое число является типом с фиксированным битом. Если они могут содержать сколь угодно большие математические целые числа, radixsort будет O (n log n) также.)

1
ответ дан 29 November 2019 в 02:27
поделиться

Нет, не без предположений о числах / упорядочивании.

Это было бы возможно, учитывая отсортированный список.

0
ответ дан 29 November 2019 в 02:27
поделиться

Кажется, возможно отсортировать неограниченный набор целых чисел за время O (n * sqrt (log (log (n)))). После сортировки, конечно тривиально найти минимальную разницу в линейном времени.

Но я не могу придумать никакого алгоритма, чтобы сделать это быстрее, чем этот.

1
ответ дан 29 November 2019 в 02:27
поделиться

Я думаю, что ответ отрицательный, и доказательство похоже на доказательство того, что вы не можете сортировать быстрее, чем n lg n: вам нужно сравнить все элементы, т.е. создать дерево сравнения, что подразумевает алгоритм омега (n lg n).

EDIT . Хорошо, если вы действительно хотите поспорить, тогда вопрос не говорит о том, должна ли это быть машина Тьюринга или нет. С помощью квантовых компьютеров вы можете делать это за линейное время :)

0
ответ дан 29 November 2019 в 02:27
поделиться

Я не думаю, что вы сможете это сделать за O (n). Лучшее, что я могу придумать, это отсортировать их (что составляет O (n * log n)) и найти минимальную разницу между соседними парами в отсортированном списке (что добавляет еще O (n)).

6
ответ дан 29 November 2019 в 02:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: