最近,我在perl中遇到了以下代码,它返回所有传递参数中的最小数值。
return 0 + ( sort { $a <=> $b } grep { $_ == $_ } @_ )[0];
我通常使用简单的线性搜索来查找列表中的最小值/最大值,这对我来说似乎很简单且充分优化。以上代码是否比简单的线性搜索更好?在这种情况下与perl有什么关系?谢谢!
答案 0 :(得分:4)
O()没有说算法需要多长时间。例如,在其他条件相同的情况下,我总是在以下两个中选择算法2:
O()指定算法在输入大小增加时 scale 所用的时间。 (好吧,它可以用于任何资源,而不仅仅是时间。)由于前两个答案只是用O()来讨论,所以它们没用。
如果你想知道哪种算法对于给定大小的输入更好的算法有多快,你需要对它们进行基准测试。
在这种情况下,看起来List::Util的min
总是明显更好。
$ 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);
答案 1 :(得分:2)
你是对的。如果您不需要将排序数据用于任何其他目的,则简单线性搜索最快。为了完成它的工作,无论如何,排序必须至少查看一次每个数据。
只有当排序的数据对其他用途有用时 - 或者当我不关心运行时间,功耗,散热等 - 我才会对数据进行排序以找到最小值和最大值。 / p>
现在,@ SimeonVisser是正确的。排序确实有 O(n * log(n))。 这并不像许多程序员想象的那样慢于 O(n)。 在感兴趣的实际情况中,管理排序的平衡二叉树(或其他此类结构)的开销可能与 log(n)因子一样重要。所以,人们不必因排序的前景而惊恐万分!但是,线性搜索仍然更快:你对此非常正确。
此外,@ DavidO添加了这样一个富有洞察力的评论,我会用他自己的话来引用它:
线性搜索也是一种更容易概括的算法。例如,线性搜索可以容易地(并且相对有效地)基于磁盘用于大数据集。而基于磁盘的排序变得相对昂贵,而如果不是字段大小则更复杂 归一化的。
答案 2 :(得分:0)
线性搜索是O( n ),原因很明显。排序为O( n log n )(请参阅Perl文档中的sort)。所以是的,线性搜索在复杂性方面确实更快。这不仅适用于Perl,也适用于任何实现这些算法的编程语言。
与许多问题一样,有多种方法可以解决它,并且还有多种方法可以获得列表的最小值/最大值。从概念上讲,当你只想要列表的最小值或最大值时,线性搜索会更好,因为问题不会要求排序。