Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

given an array of integers in random order you have to find the minimum number of swaps to convert it to cyclic sorted array

if an array is given in random order , you have to output the minimum number of swaps required to convert into cyclic sorted array.

e.g. array given is 3 5 4 2 1

so the first swap will be 5<-->4 result : 3 4 5 2 1 second swap will be 2<-->1 result : 3 4 5 1 2 (final)

output : 2

i am not able to get the logic behind this problem.

adding some more : swap only possible between adjacent elements and numbers are between range 1 to N

like image 802
user2161522 Avatar asked Mar 12 '13 14:03

user2161522


2 Answers

Well, don't know if it is the best algorithm available, but I can think of a O(n^2) solution:

First, ignore the possibility of the cyclic array. Let's solve a simpler problem: what is the minimum number of swaps to sort an array.

Be careful here, because this isn't about sorting algorithms. A comparation-based sorting algorithm would have a worst-case of at least O(n log n). In this problem, the maximum number of swaps you need is n.

Why? Because it's the maximum permutation cycle size you can achieve. The minimum number of swaps you need is exactly the permutation cycle size minus one. I mean you can represent any permutation of the array as a permutation cycle, e.g.:

3 2 1 4 5 -> (2)(4)(5)(1 3)

For the permutations cycles of size 1, you don't need any swap. For the permutation cycle of size 2, you need exactly 1 swap. This scales as:

2 3 4 5 1 -> (1 2 3 4 5)

Ignoring this array is already cyclic-sorted, this array is tottaly messed. To sort it normally, I would need 4 swaps, basically moving the 1 to it's normal position.

Calculating the permutation cycles is pretty easy, it's just a matter of following the number to where it should be if the array was sorted. Using the previous examples

3 2 1 4 5

  • Starts at A[0];
  • Because A[0]==3, and 3 would be the 3rd element in sorted array, follows to 3rd position;
  • Because A[2]==1, and 1 would be..., follows to 1st position. As we were already there here we have a cycle of size 2;

  • Starts again at next unvisited position (1)

  • A[1]==2 is in it's right position, so we don't need to do anything, here we have a cycle of size 1.

  • and so forth...

This algorithm is O(n), but as we need to do this for the array starting in every possible position (because it is circular), we would do it n times, so, the entire algorithm is O(n^2).

UPDATE; some python code to show my algorithm:

def offset_swaps(A, S, offset):
    visited = [False]*len(A)
    swaps = 0

    for i in xrange(len(A)):
        if visited[i]: continue

        cycle, current = 0, i
        while not visited[current]:
            cycle += 1
            visited[current] = True
            current = (S[A[current]] + offset) % len(A)

        swaps += cycle - 1

    return swaps       

def number_of_swaps(A):
    S = {x:i for i,x in enumerate(sorted(A))}
    min_swaps = len(A)
    for i in xrange(len(A)):
        min_swaps = min(min_swaps, offset_swaps(A, S, i))
    return min_swaps

print number_of_swaps((3, 5, 4, 2, 1))
like image 68
Juan Lopes Avatar answered Nov 14 '22 04:11

Juan Lopes


I think the approach here should be - sort all the numbers into a helper array. Then for each cyclic shift calculate the number of swaps needed to get the original array to this cyclic shift. Choose the minimal of those.

To find minimal number of swaps required to get array A to array B simply count the number of interchanged values(i.e. value a is on the left of value b in A but vice versa in array B). This problem is equivelent to counting the inversions in a given array and can be solved using modified merge sort again in O(n*log(n)).

The complexity of my approach is O(n^2*log(n))(because you do a merge sort for all cyclic shifts of an array of size n).

I can not think of a faster solution for your problem.

like image 43
Ivaylo Strandjev Avatar answered Nov 14 '22 05:11

Ivaylo Strandjev