Yes, stick with the binary search. Just change the terminating condition from
$query == $array->[$center]
to
$query == $array->[$center] && ($begin
? ($center == 0 || $query != $array->[$center-1])
: ($center == $#$array || $query != $array->[$center+1])
)
You check the condition a second and third time later down, so you need to fix those too.
All together:
sub binarySearch {
my ($begin, $query, $array) = @_;
return 0 if $query < $array->[0] and $begin == 1;
return $#$array if $query > $array->[$#$array] and $begin == 0;
my ($left, $right, $prevCenter) = (0, $#$array, -1);
while(1) {
my $center = int (($left + $right)/2);
my $cmp = $query <=> $array->[$center]
|| ($begin
? ($center == 0 || $query != $array->[$center-
+1] ? 0 : -1)
: ($center == $#$array || $query != $array->[$center+
+1] ? 0 : +1)
);
return $center if $cmp == 0;
if ($center == $prevCenter) {
return $right if $begin == 1;
return $right-1 if $begin == 0;
}
$right = $center if $cmp < 0;
$left = $center if $cmp > 0;
$prevCenter = $center;
}
}
Update: Added code.
|