2009-10-30 3 views
5

Я пытаюсь найти алгоритм, чтобы найти самые высокие 2 числа в списке чисел.Найти самые высокие 2 цифры - информатика

Наибольшее число можно найти на этапах n-1, возможно, выполняя первый шаг пузырьковой сортировки или что-то в этом роде. Мне кажется, что найти следующий самый высокий номер также можно было найти в среднем на 1,5n сравнений в среднем.

Мой профессор задал нам домашнюю работу, чтобы написать алогритм, который находит наивысшие 2 числа в n + log (n) сравнениях. Возможно ли это? Любые идеи, предложения?

Edit: Когда я говорю, п + LOG (п) я не имею в виду О (п + § п), а именно п + п войти

+0

См вопрос нет. 1602998 –

+2

вот удобная ссылка: http://stackoverflow.com/questions/1602998 – nickf

+0

Должны ли номера быть разными? Например. В списке (1, 3, 2, 3) указаны два самых высоких числа (3, 3) или (2, 3)? – 2009-10-30 10:42:37

ответ

6

Да, это возможно сделать не более (n + log n). Я действительно не могу сказать вам, как не отказать в ответе, но позвольте мне попробовать. :-)

Возьмите n чисел, сравните их по парам за раз. Возьмите ceil (n/2) «победители» и повторите «как двоичное дерево». Вопросы: сколько сравнений требуется, чтобы найти самый большой? Сколько людей побеждает этот «победитель»? Кому может потерять второй по величине? Итак, сколько сравнений теперь требуется, чтобы найти второе по величине число?

Ответ оказывается в общей сложности п-1 + потолок (Log N) - 1 сравнений, где Бревно базировать 2. Вы можете также доказать, используя состязательный аргумент, что это не представляется возможным делайте лучше, чем это, в худшем случае.

+0

Спасибо. Такой простой, но умный. Теперь я попытаюсь запрограммировать его рекурсивно и эффективно в Java ... – Meir

0

Как об этом:

for each listOfNumbers as number 
    if number > secondHighest 
     if number > highest 
      secondHighest = highest 
      highest = number 
     else 
      secondHighest = number 
+1

Для этого требуется сравнение «O (2n)», которое больше, чем «O (n + log (n))». –

+0

Вышеупомянутое относится к наихудшему времени работы, если номера хранятся в порядке возрастания. –

+4

O (2n) совпадает с O (n), так что комментарий не имеет смысла. – 2009-10-30 10:42:01

2

Редактировать: Ой, пропустил простую вещь из-за глупости. Это решение неверно, хотя я сохраняю его здесь, поскольку он все еще avg (n + log (n)). Спасибо ShreevatsaR за то, что я указал на свою глупость. Я действительно рассматривал поиск дерева, но полностью пропустил идею отступления, чтобы найти второе по величине число в log (n).

В любом случае, здесь следует мое доказательство того, почему нижний алгоритм не превышает avg (n + log (n)). В реальной жизни он должен по-прежнему работать довольно неплохо.

  • Первое сравнение с вторым самым высоким записанным номером.
  • Только если это сравнение будет успешным, сравните его с самым высоким записанным числом.

Чтобы доказать, что оно находится в среднем n + log n, нам просто нужно доказать, что первое сравнение успевает в среднем log (n) раз. И это довольно просто увидеть или продемонстрировать.

  1. Пусть P в качестве фактического положения тока второго по величине числа в отсортированной версии списка, и запустить алгоритм
  2. Если P> 2, то, когда большее число найдено, новая должность будет в среднем не более P/2.
  3. Если P = 2, то первое сравнение не может быть успешным, так как нет числа, которое больше текущего второго по величине числа.
  4. P может быть не более равным N
  5. От 2, 3 и 4 должно быть тривиально видеть, что первое сравнение не может быть больше, чем log (N) раз в среднем.
+1

Ваши первые строки неверны: вам не нужны 2 * n сравнения в худшем случае, и на самом деле это можно сделать в точно (n-1) + потолок (log n) -1, сравнения, как задает вопрос. Я не делаю этого, потому что остальная часть ответа правильная, но на самом деле «я не могу придумать способ» не является доказательством. : P – ShreevatsaR

0

Ответ отправил ShreevatsaR, кажется, O (n log n).

Первый проход (n операций) производит n/2 ответа. Повторяю, я думаю, вы имеете в виду, что вы будете выполнять n/2 операции для получения n/4 ответов. Вы будете проходить журнал цикла n раз. Это очень похоже на сортировку слияния, за исключением того, что сортировка слияния всегда обрабатывает n узлов каждый раз. Он также запускает журнал цикла n раз. И я не вижу, как этот алгоритм будет отслеживать второе самое высокое число.

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

btw, O (n + log n) - O (n), обозначение порядка относится к наихудшему асимптотическому росту.

+0

Э? n/2 + n/4 + ... = n-1. (Еще один способ увидеть это: все, кроме победителя, проигрывают ровно один раз.) Алгоритм, который я дал, дает ровно n + log (n) -2 сравнения (не просто асимптотически). Обратите внимание, что рассматриваемая мера - это количество сравнений, а не время выполнения. (Но n + log (n) - O (n), поэтому время выполнения равно O (n).) Мне жаль, что мой ответ неясен, но я не хочу полностью отдать ответ на домашнее задание вопрос. – ShreevatsaR

0

Вы можете использовать сортировку подсчета, сортировку по методу radix, сортировку ковша или другой алгоритм линейного времени, чтобы отсортировать список в порядке убывания. Затем просто получите первые 2 элемента отсортированного списка. Таким образом, это займет (n) + 2 = (n)

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

+0

(1) Ничего не гарантировано в отношении заданных чисел, поэтому сортировка по линейному времени невозможна. (2) Обратите внимание, что здесь мера - это количество сравнений, а не количество операций (3). Обратите внимание, что она запрашивает * точно * n + log (n), а не O (n + log (n)), что быть просто O (n). – ShreevatsaR

0

псевдокод (не это по существу п?)

int highestNum = 0 
int secondHighest = highestNum 

for(i = 0; i < list.length; i++) 
{ 
if(list[i] >= highestNum) 
{ 
secondHighest = highestNum 
highestNum = list[i] 
} 
} 
+1

Тестирование в этом списке: 0 3 2 1. Второе место будет оставаться 0.(В более общем плане, возьмите любой список, где наибольшее число встречается перед вторым самым большим числом, и ваш код будет пропустить второй по высоте.) – ShreevatsaR

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