Squeak.ru - шаблоны программирования

Сортировка против линейного поиска для нахождения минимума/максимума

Недавно я наткнулся на следующий фрагмент кода на Perl, который возвращает минимальное числовое значение среди всех переданных аргументов.

return 0 + ( sort { $a <=> $b } grep { $_ == $_ } @_ )[0];

Я обычно использую простой линейный поиск, чтобы найти минимум/максимум в списке, который мне кажется простым и достаточно оптимальным. Является ли приведенный выше код лучше, чем простой линейный поиск? Что делать с perl в этом случае? Спасибо!


Ответы:


1

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

  • Алгоритм 1: O(2*N + 1000 дней) = O(N)
  • Алгоритм 2: O(5*N + 100 мс) = O(N log N)

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

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

В этом случае min для List::Util равно всегда значительно лучше.

$ perl x.pl 10
           Rate  sort LUmin
sort  1438165/s    --  -72%
LUmin 5210584/s  262%    --

$ perl x.pl 100
           Rate  sort LUmin
sort   129073/s    --  -91%
LUmin 1485473/s 1051%    --

$ perl x.pl 1000
          Rate  sort LUmin
sort    6382/s    --  -97%
LUmin 199698/s 3029%    --

Код:

use strict;
use warnings;

use Benchmark  qw( cmpthese );
use List::Util qw( min );

my %tests = (
   'sort'  => 'my $x = ( sort { $a <=> $b } @n )[0];',
   'LUmin' => 'my $x = min @n;',
);

$_ = 'use strict; use warnings; our @n; ' . $_
   for values %tests;

local our @n = map rand, 1..( $ARGV[0] // 10 );
cmpthese(-3, \%tests);
07.06.2012
  • Вау, это исчерпывающее объяснение! Какой метод используется List::Util::min для вычисления минимального значения? 08.06.2012
  • @Sanjay, это линейный поиск, написанный на C. 08.06.2012

  • 2

    Ты прав. Если вам не нужны отсортированные данные для какой-либо другой цели, простой линейный поиск будет самым быстрым. В любом случае, чтобы выполнить свою работу, сортировка должна просмотреть каждое данное как минимум один раз.

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

    Теперь @SimeonVisser прав. Сортировка имеет O(n*log(n)). Это не намного медленнее, чем O(n), как думают многие программисты. В практических случаях накладные расходы на управление сбалансированным двоичным деревом сортировки (или другой подобной структурой), вероятно, имеют такое же значение, как и фактор log(n). Так что не надо пугаться перспективы сортировки! Однако линейный поиск все же быстрее: в этом вы совершенно правы.

    Более того, @DavidO добавляет такой проницательный комментарий, что я бы процитировал его здесь своими словами:

    Линейный поиск также является более простым алгоритмом для обобщения. Например, линейный поиск может быть легко (и относительно эффективно) основан на диске для больших наборов данных. Принимая во внимание, что сортировка на основе диска становится относительно дорогой и даже более сложной, если размеры полей не нормализованы.

    07.06.2012
  • Линейный поиск также является более простым алгоритмом для обобщения. Например, линейный поиск может быть легко (и относительно эффективно) основан на диске для больших наборов данных. Принимая во внимание, что сортировка на основе диска становится относительно дорогой и даже более сложной, если размеры полей не нормализованы. 07.06.2012
  • При прочих равных O(N log N) в 10 раз медленнее, чем O(N) при N = 1000. Это немало. Конечно, реальный ответ, вероятно, заключается в том, что O() совершенно не имеет отношения к вопросу ОП, как я объяснил в своем ответе. 07.06.2012
  • @ikegami: Ты прав. Однако, как известно, нотация O() вводит программистов в заблуждение, что я и пытался подчеркнуть. Алгебраически log(n) имеет нулевой порядок — точно нулевой, точно так же, как константа типа 1 имеет алгебраический нулевой порядок. Почему? Из-за правления Лопиталя; или, если хотите, потому что log(n)/n^epsilon сходится для положительного эпсилон и расходится для отрицательного эпсилон, даже если < i>эпсилон крошечный. Стоит подумать, насколько O(sqrt(n)) хуже, чем O(log(n)). Действительно, O(log(n)) больше похож на O(1), чем думают многие программисты. 08.06.2012

  • 3

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

    Как и во многих других задачах, существует несколько способов ее решения, а также несколько способов получить минимальное/максимальное значение списка. Концептуально я бы сказал, что линейный поиск лучше, когда вам нужен только минимум или максимум списка, поскольку проблема не требует сортировки.

    07.06.2012
  • s/действительно быстрее с точки зрения сложности/действительно лучше масштабируется по мере увеличения размера ввода/. O(N) ничего не говорит вам о скорости. Например, алгоритму O(N) может потребоваться 1200 дней для обработки 100 элементов (2*N + 1000 дней). 07.06.2012
  • Новые материалы

    Угловая структура архитектуры
    Обратите внимание, что эта статья устарела, я решил создать новую с лучшей структурой и с учетом автономных компонентов: https://medium.com/@marekpanti/angular-standalone-architecture-b645edd0d54a..

    «Данные, которые большинство людей используют для обучения своих моделей искусственного интеллекта, поставляются со встроенным…
    Первоначально опубликовано HalkTalks: https://hacktown.com.br/blog/blog/os-dados-que-a-maioria-das-pessoas-usa-para-treinar-seus-modelos-de-inteligencia-artificial- ja-vem-com-um-vies-embutido/..

    Сильный ИИ против слабого ИИ: различия парадигм искусственного интеллекта
    В последние годы изучению и развитию искусственного интеллекта (ИИ) уделяется большое внимание и прогресс. Сильный ИИ и Слабый ИИ — две основные парадигмы в области искусственного интеллекта...

    Правильный способ добавить Firebase в ваш проект React с помощью React Hooks
    React + Firebase - это мощная комбинация для быстрого и безопасного создания приложений, от проверки концепции до массового производства. Раньше (знаете, несколько месяцев назад) добавление..

    Создайте API с помощью Python FastAPI
    Создание API с помощью Python становится очень простым при использовании пакета FastAPI. После установки и импорта вы можете создать приложение FastAPI и указать несколько конечных точек. Каждой..

    Веселье с прокси-сервером JavaScript
    Прокси-серверы JavaScript — это чистый сахар, если вы хотите создать некоторую общую логику в своих приложениях, чтобы облегчить себе жизнь. Вот один пример: Связь клиент-сервер Мы..

    Получить бесплатный хостинг для разработчиков | Разместите свой сайт за несколько шагов 🔥
    Статические веб-сайты — это веб-страницы с фиксированным содержанием и его постоянным содержанием. Но теперь статические сайты также обрабатывают динамические данные с помощью API и запросов...