[英]Reducing time complexity in Perl arrays
我有一個數組
[3, 1, 2, 5, 4, 6]
我想排序(更改sort
,以arranging in a certain pattern
)這是:移動到右,與右側的下一個最大的整數更換指標。 在這個數組中說3
被5
替換,1被2
替換,依此類推。
我希望輸出為
[5, 2, 5, 6, 6, 6]
算法:
這是一個正常的算法。 但是時間復雜度是n * n。 (不完全是n * n)。
有沒有辦法降低復雜度。 因為在大型陣列的情況下,它會非常慢。 有人可以為我提供時間復雜度n
算法嗎?
添加代碼
use strict;
use warnings;
my @arr1 = qw/3 1 2 5 4 6/;
my @arr2;
my ($j, $i);
for($i = 0; $i <= $#arr1; $i++) {
$j = $i;
while ( $j < $#arr1) {
if ( $arr1[$i] < $arr1[$j+1]) {
push @arr2,$arr1[$j+1];
last;
}
if ($i == $#arr1) {
push @arr2,$arr1[$j];
}
$j++;
}
}
push @arr2, $arr1[$#arr1]; ## Pushing the last array index
print @arr2;
輸出:
525666
您當前的算法可以多次觸摸一個位置,效率低下。 通過遞歸的力量,我們可以做得更好。 想象一個函數執行您的排序,直到發現一個大於$n
:
[3, 1, 2, 5, 4, 6] # start here
#^
[3, 1, 2, 5, 4, 6] # look at next number. It's smaller, so we recurse
#^--^
[3, 1, 2, 5, 4, 6] # in recursion: look at next number, replace
#^ ^--^
#|__|
[3, 2, 2, 5, 4, 6] # return new index. It's smaller, so we recurse
#^ ^
#|_____|
[3, 2, 2, 5, 4, 6] # in recursion: look at next number, replace
#^ ^--^
#|_____|
[3, 2, 5, 5, 4, 6] # return new index
#^ ^
#|________|
[3, 2, 5, 5, 4, 6] # It's larger, so we replace and go to new index
#^--------^
[5, 2, 5, 5, 4, 6] # Look at next number. It's smaller, so we recurse
# ^--^
[5, 2, 5, 5, 4, 6] # In recursion: replace
# ^ ^--^
# |__|
[5, 2, 5, 5, 6, 6] # return new index
# ^ ^
# |_____|
[5, 2, 5, 5, 6, 6] # It's larger, so we replace. Go to new index
# ^-----^
[5, 2, 5, 6, 6, 6] # Done!
困難的部分是編寫執行此操作的函數。 當我們想編寫一個遞歸函數時,我們必須回想一下:
[]
–空數組(無索引)對自身進行排序 [6]
–帶有單個元素的數組將對該元素進行排序 [4, 6] → [6, 6]
–如果下一個索引處的元素較大,則將其復制過來,新索引位於下一個元素處 [5, 4, ...]
–如果下一個元素較小,則從該索引處遞歸。 示例實現:
sub weird_sort {
my ($array, $start, $return) = @_;
$start //= 0;
my $next = $start + 1;
while ($next <= $#$array) {
# check if one is larger
if ($array->[$start] < $array->[$next]) {
$array->[$start] = $array->[$next];
return $next if $return; # return index to higher levels so that they
# can check whether the $next elem is larger.
$start = $next;
$next = $start + 1;
}
else {
$next = weird_sort($array, $next, 1);
}
}
return $next;
}
# called in-place like
weird_sort(\@array);
下一步將是刪除遞歸:
sub weird_sort {
my ($array) = @_;
my ($start, $next) = (0, 1);
my @stack;
while ($next <= $#$array) {
# check if one is larger
if ($array->[$start] < $array->[$next]) {
$array->[$start] = $array->[$next];
($start, $next) = @stack ? (pop(@stack), $next) : ($next, $next + 1);
}
else {
push @stack, $start;
($start, $next) = ($next, $next + 1);
}
}
}
這似乎適用於簡單的情況,但我不能完全確定這是一個通用的解決方案。
我認為這不是N * N的復雜性。 到更大值的平均距離不會隨着數組的增長而增加,因此您的復雜度會以N而不是N * N的比率增加。 你為什么不發布一些代碼? 如果評估需要很長時間,則可能是您的實現中存在錯誤。
通過不對重新排序的數據使用新數組,您現有的算法將更快。 在我的筆記本電腦上,使用下面的測試程序,速度大約提高了60%,其中100萬個元素被輕度隨機
use strict;
use warnings;
#my @arr1 = qw/3 1 2 5 4 6/;
my @arr1= ( 1 .. 1000000 );
for (@arr1) { my $r1=rand($#arr1); my $r2=rand($#arr1); @arr1[$r1,$r2]=@arr1[$r2,$r1] }
my @arr2;
my ($j, $i);
for($i = 0; $i <= $#arr1; $i++) {
$j = $i;
while ( $j < $#arr1) {
if ( $arr1[$i] < $arr1[$j+1]) {
$arr1[$i] = $arr1[$j+1];
last;
}
$j++;
}
}
#print @arr1;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.