Counting inversions in an array

前端 未结 30 1969
死守一世寂寞
死守一世寂寞 2020-11-22 04:14

I\'m designing an algorithm to do the following: Given array A[1... n], for every i < j, find all inversion pairs such that A[i] > A[j]

30条回答
  •  栀梦
    栀梦 (楼主)
    2020-11-22 04:42

    Here is O(n*log(n)) perl implementation:

    sub sort_and_count {
        my ($arr, $n) = @_;
        return ($arr, 0) unless $n > 1;
    
        my $mid = $n % 2 == 1 ? ($n-1)/2 : $n/2;
        my @left = @$arr[0..$mid-1];
        my @right = @$arr[$mid..$n-1];
    
        my ($sleft, $x) = sort_and_count( \@left, $mid );
        my ($sright, $y) = sort_and_count( \@right, $n-$mid);
        my ($merged, $z) = merge_and_countsplitinv( $sleft, $sright, $n );
    
        return ($merged, $x+$y+$z);
    }
    
    sub merge_and_countsplitinv {
        my ($left, $right, $n) = @_;
    
        my ($l_c, $r_c) = ($#$left+1, $#$right+1);
        my ($i, $j) = (0, 0);
        my @merged;
        my $inv = 0;
    
        for my $k (0..$n-1) {
            if ($i<$l_c && $j<$r_c) {
                if ( $left->[$i] < $right->[$j]) {
                    push @merged, $left->[$i];
                    $i+=1;
                } else {
                    push @merged, $right->[$j];
                    $j+=1;
                    $inv += $l_c - $i;
                }
            } else {
                if ($i>=$l_c) {
                    push @merged, @$right[ $j..$#$right ];
                } else {
                    push @merged, @$left[ $i..$#$left ];
                }
                last;
            }
        }
    
        return (\@merged, $inv);
    }
    

提交回复
热议问题