views:

494

answers:

2

Hello, suppose I have a vector:

 0  1  2  3  4  5
[45,89,22,31,23,76]

And a permutation of its indices:

[5,3,2,1,0,4]

Is there an efficient way to resort it according to the permutation thus obtaining:

[76,31,22,89,45,23]

Using at most O(1) additional space?

+7  A: 

Yes. Starting from the leftmost position, we put the element there in its correct position i by swapping it with the (other) misplaced element at that position i. This is where we need the O(1) additional space. We keep swapping pairs of elements around until the element in this position is correct. Only then do we proceed to the next position and do the same thing.

Example:

[5 3 2 1 0 4] initial state

[4 3 2 1 0 5] swapped (5,4), 5 is now in the correct position, but 4 is still wrong

[0 3 2 1 4 5] swapped (4,0), now both 4 and 0 are in the correct positions, move on to next position

[0 1 2 3 4 5] swapped (3,1), now 1 and 3 are both in the correct positions, move on to next position

[0 1 2 3 4 5] all elements are in the correct positions, end.

Note:

Since each swap operation puts at least one (of the two) elements in the correct position, we need no more than N such swaps altogether.

Zach Scrivena
Another way of looking at this solution is to say that you're following the cycle representation of the permutation. [ http://mathworld.wolfram.com/PermutationCycle.html ]
ShreevatsaR
That's exactly right! =)
Zach Scrivena
Thank you very much, your answer helped :)
tunnuz
+6  A: 

Zach's solution is very good.

Still, I was wondering why there is any need to sort. If you have the permutation of the indices, use the values as a pointer to the old array.

This may eliminate the need to sort the array in the first place. This is not a solution that can be used in all cases, but it will work fine in most cases.

For example:

a = [45,89,22,31,23,76];
b = [5,3,2,1,0,4]

Now if you want to lop through the values in a, you can do something like (pseudo-code):

for i=0 to 4
{
    process(a[i]);
}

If you want to loop through the values in the new order, do:

for i=0 to 4
{
    process(a[b[i]]);
}

As mentioned earlier, this soluion may be sufficient in many cases, but may not in some other cases. For other cases you can use the solution by Zach.But for the cases where this solution can be used, it is better because no sorting is needed at all.

Niyaz
Your answer helped as well, in translating the permutation vector to use it to permute rows or columns of a matrix.
tunnuz