Enumerate grid points on 2D plane with descending order of (x * y)

前端 未结 8 1269
轻奢々
轻奢々 2021-02-09 11:55

Given N > 0 and M > 0, I want to enumerate all (x, y) pairs such that 1 <= x <= N and 1 <= y <= M in descending order of (x * y). An

8条回答
  •  北荒
    北荒 (楼主)
    2021-02-09 12:02

    I got it!

    Consider the grid as a set of M columns where every column is a stack containing the elements from 1 at the bottom to N at the top. Every column is tagged with its x coordinate.

    The elements inside every column stack are ordered by its y value and so also by x*y as x has the same value for all of them.

    So, you just have to go picking the stack that has the bigger x*y value at its top, pop it and repeat.

    In practice you will not need stacks, just the index of the top value and you can use a priority queue to get the column with the bigger x*y value. Then, decrement the value of the index and if it is bigger than 0 (indicating that the stack has not been exhausted) reinsert the stack on the queue with its new priority x*y.

    The complexity of this algorithm for N=M is O(N2logN) and its memory usage O(N).

    Update: Implemented in Perl...

    use Heap::Simple;
    
    my ($m, $n) = @ARGV;
    
    my $h = Heap::Simple->new(order => '>', elements => [Hash => 'xy']);
    # The elements in the heap are hashes and the priority is in the slot 'xy':
    
    for my $x (1..$m) {
        $h->insert({ x => $x, y => $n, xy => $x * $n });
    }
    
    while (defined (my $col = $h->extract_first)) {
        print "x: $col->{x}, y: $col->{y}, xy: $col->{xy}\n";
        if (--$col->{y}) {
            $col->{xy} = $col->{x} * $col->{y};
            $h->insert($col);
        }
    }
    

提交回复
热议问题