Reputation: 2023
I am having a array
[3, 1, 2, 5, 4, 6]
I want to sort ( Changed sort
to arranging in a certain pattern
) this as : Move to right and replace the index with next highest integer on right side. Say in this array 3
is replaced by 5
, 1 is replaced by 2
and so on..
I want the output as
[5, 2, 5, 6, 6, 6]
Algorithm :
It is a normal algorithm. But the time complexity is n*n. (No exactly n*n).
Is there a way to reduce the complexity. Because in case of large arrays, it would be very slow. Can somebody provide me algorithm for time complexity n
.
Adding code
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;
Output:
525666
Upvotes: 0
Views: 304
Reputation: 57600
Your current algorithm can touch one position multiple times, which is inefficient. By the power of recursion, we could do better. Imagine a function that performs your sort until it finds a number higher than some $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!
The difficult part is to write a function that does this. As we want to write a recursive function, we have to think backwards:
[]
– empty array (no indices left) sorts to itself[6]
– array with single element left sorts to that element[4, 6] → [6, 6]
– if the element at the next index is larger, copy it over and the new index is at the next element[5, 4, ...]
– if the next element is smaller, recurse at that index.Example implementation:
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);
The next step would be to remove the recursion:
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);
}
}
}
This seems to work for simple cases, but I'm not entirely certain that this is a general solution.
Upvotes: 5
Reputation: 34307
By not using a new array for the reordered data your existing algorithm goes faster. With the test program below on my laptop this is about 60% faster with 1 million elements mildly randomized
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;
Upvotes: 1
Reputation: 85
I don't think it is N*N complexity. The average distance to a larger value does not increase as the array grows, so your complexity increases at the rate of N not N*N. Why don't you post some code? If it is taking a long time to evaluate, perhaps you have an error in your implementation.
Upvotes: 1