【发布时间】:2012-09-02 06:36:05
【问题描述】:
有一个数组最多可以包含1000 个元素。它可以产生的数字范围是1 to 10^10。现在我必须在数组中的两个数字之间找到minimal absolute difference。我想到了两种算法:
对于第一个,我定义了一个binarysearch 函数,该函数在排序数组中查找要插入的数字的位置。现在我只用给定数组的第一个数字开始排序数组,并从第二个元素开始迭代给定数组。对于每个数字,我找到它在排序数组中的位置。如果那个位置的数字是这个数字,那么差是0,它是可能的最低值,所以我退出循环。否则,我在该点将数字插入排序数组中,然后检查该数字与该数组中的前一个和下一个数字之间的差异。然后我存储这个结果和上一个结果的最小值,并以这种方式继续。
第二:我使用快速排序对数组进行排序。 (范围太大,所以我认为基数排序不会那么有效)。然后我对其进行迭代,如果两个连续数字相等,则返回 0 的答案,否则存储该数字与前一个数字和前一个结果之间的差的最小值。
哪个效率更高?
还有更好的算法吗?
Stackoverflow 有很多关于这方面的帖子,但它们并没有太大帮助。这是我在 Perl 中的代码:
sub position {
my @list = @{$_[0]};
my $target = $_[1];
my ($low,$high) = (0, (scalar @list)-1);
while ($low <= $high) {
$mid = int(($high + $low)/2);
if ( $list[$mid] == $target ) {
return $mid;
}
elsif ( $target < $list[$mid] ) {
$high = $mid - 1;
}
else {
$low = $mid + 1;
}
}
$low;
}
sub max { $_[0] > $_[1] ? $_[0] : $_[1]; }
sub min { $_[0] > $_[1] ? $_[1] : $_[0]; }
$ans = 10_000_000_000;
@numbers = (234, 56, 1, 34...123); #given array
($max,$min) = @num[0, 0];
@sorted = ($numbers[0]);
for ( @num[1 .. $#num] ) {
$pos = position(\@sorted, $_);
if ( $sorted[$pos] == $_ ) {
$ans = 0;
last;
}
splice @sorted, $pos, 0, $_;
if ( $#sorted == $pos ) {
$ans = min($_-$sorted[-2], $ans);
}
elsif ( 0 == $pos ) {
$ans = min($sorted[1]-$_, $ans);
}
else {
$ans = min(min(abs($sorted[$pos-1]-$_), abs($sorted[$pos+1]-$_)), $ans);
}
$max = max($_, $max);
$min = min($_, $min);
}
print "$ans\n";
【问题讨论】:
-
会经常发生吗?否则,1000 个元素真的没什么大不了的——而且很可能不值得你花时间优化它
-
它最多可以包含大约 5000 个元素。
-
仍然很小。除非它经常发生,否则任何优化都不值得您花时间
-
要了解它有多小:sandy-bridge 处理器有 32KB L1-Cache。假设 4 字节整数,它最多可以支持 8192 个整数。如果您真的想优化解决方案 - 专注于尽可能缓存友好的解决方案,并尽可能避免创建更多数据。就地快速排序可能会胜过任何其他解决方案
-
请使用pragma
use strict;,对你有帮助!
标签: algorithm perl sorting binary-search