找到数组中两个数字之间最小绝对差的最佳算法

前端之家收集整理的这篇文章主要介绍了找到数组中两个数字之间最小绝对差的最佳算法前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
有一个数组,可以包含多达1000个元素。它可以产生的数字范围是1到10 ^ 10。现在我必须找到数组中两个数字之间的最小绝对差。我已经想到了两种算法:

对于第一个,我已经定义了一个二进制搜索函数,它查找排序数组中被插入数字的位置。现在我启动排序数组,只有给定数组的第一个数字,并从第二个元素开始对给定的数组进行迭代。对于每个数字,我在排序的数组中找到它的位置。如果该位置的数字是这个数字,则差值为0,这是最低的数值,所以我退出循环。否则,我在该点将数字插入排序的数组,然后检查该数字与该数组中的前一个和下一个数字之间的差异。然后我存储此结果的最小值和以前的结果,并以此方式继续。

第二:我使用quicksort对数组进行排序。 (范围太大,所以我认为基数排序不会那么有效)。然后我重复一遍,如果两个连续的数字相等,则用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,$_;

    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";

解决方法

你最多有5k个元素。

请注意,sandy bridge处理器具有32KB L1-Cache,假设为4字节整数 – 这意味着它可以包含8192个整数。

我会尽量避免创建额外的数据(除了计数器等等),并使用相同的数组来做所有事情。这将使得cache-misses数量非常小,并且可能会超出任何算法。

因此,一个就地快速排序,而不是迭代数组中的元素,可能会比任何其他解决方案更好,无论是缓存高效还是保持O(nlogn)的体面渐近的复杂性。

注意 – 虽然这个解决方案可能会更有效率(至少在理论上),但是规模还是非常小的,除非你要做这么多的时间,否则你的时间过于优化。

一般提示:当谈到小规模问题(最多5000个元素符合这个标准)时,大O符号通常是不够的。缓存性能通常是这些问题的主要因素。

猜你在找的Perl相关文章