Reputation: 4043
supposed I have an array of integers:
1 2 5 3 7 6
What is a simple enough algorithm that determines if this is an even or odd permutation of the numbers in sorted fashion (i.e. 1 2 3 5 6 7
)? Performance is not terribly important here; I'd rather have a simple code.
Upvotes: 3
Views: 3911
Reputation: 31
Here is an O(n) answer.
(define (sign-of-permutation permutation)
(define p (vector-copy permutation))
(define l (vector-length p))
(define q (make-vector l))
(let iter ((i 0))
(unless (= i l)
(define x (vector-ref p i))
(vector-set! q x i)
(iter (+ i 1))))
(printf "~s\n" p)
(let iter ((i 0) (s 1))
(if (= i l)
s
(let ((x (vector-ref p i)))
(if (= i x)
(iter (+ i 1) s)
(let ((j (vector-ref q i)))
(vector-swap! p i j)
(printf "~s\n" p)
(vector-swap! q x i)
(iter (+ i 1) (- s))))))))
Here is an example.
> (define p (vector 3 4 2 0 1))
> (sign-of-permutation p)
#(3 4 2 0 1)
#(0 4 2 3 1)
#(0 1 2 3 4)
1
Upvotes: 1
Reputation: 157
See how Sympy does it. In a nutshell, here is how it works:
You can find the number of cycles, subtract it from the length of the array, take its parity, and then find the sign. Finding the number of cycles is O(N) by using a set or a boolean array to check visited values. All the other operations are O(1), so all in all, this new approach is O(N).
Upvotes: 1
Reputation: 1411
Simple and done in python for when I inevitably need to find this again:
def is_even(p):
if len(p) == 1:
return True
trans = 0
for i in range(0,len(p)):
j = i + 1
for j in range(j, len(p)):
if p[i] > p[j]:
trans = trans + 1
return ((trans % 2) == 0)
Upvotes: 1
Reputation:
Another simple code that runs in O(nlogn), and tr[] is an array with all 0s in it initially.
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=a[i];j;j-=j&-j) ans+=tr[j];
for(int j=a[i];j<=n;j+=j&-j) tr[j]++;
}
printf((n*(n-1)/2-ans)%2?"odd\n":"even");
Upvotes: 1
Reputation: 1523
Try to implement your own version of Heap Sort Algorithm having a complexity of O(n log n) and counting the number of permutation in order to build your signature (I assume you know what I'm talking about).
Sample code:
public static void HeapSort(int[] input)
{
//Build-Max-Heap
int heapSize = input.Length;
for (int p = (heapSize - 1) / 2; p >= 0; p--)
MaxHeapify(input, heapSize, p);
for (int i = input.Length - 1; i > 0; i--)
{
//Swap
int temp = input[i];
input[i] = input[0];
input[0] = temp;
heapSize--;
MaxHeapify(input, heapSize, 0);
}
}
private static void MaxHeapify(int[] input, int heapSize, int index)
{
int left = (index + 1) * 2 - 1;
int right = (index + 1) * 2;
int largest = 0;
if (left < heapSize && input[left] > input[index])
largest = left;
else
largest = index;
if (right < heapSize && input[right] > input[largest])
largest = right;
if (largest != index)
{
int temp = input[index];
input[index] = input[largest];
input[largest] = temp;
MaxHeapify(input, heapSize, largest);
}
}
Upvotes: 1
Reputation: 7650
Simple Code(Assume n numbers are stored in array a):
int f()
{
int cnt=0;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
if (a[i]>a[j]) cnt++;
return cnt%2;
}
If f() returns 0, then it is even permutation and returns 1, then it is odd.
Upvotes: 7
Reputation: 137574
According to Wikipedia, the sign is determined by the number of inversions (pairs of elements out of order). That gives an O(n**2) algorithm
Upvotes: 1
Reputation: 137574
Decompose the permutation into a product of independent cycles. Odd cycles are odd. Even cycles are even. Add up.
Upvotes: 0
Reputation: 1624
The sign of the determinant of the permutation matrix for this vector should give you the answer.
Upvotes: 0