可以使用大小为 3 的子数组旋转进行排序
给定一个整数值数组,该数组只需要按一个操作进行排序——子数组旋转,其中子数组大小应为 3。例如,如果我们的数组是 (1 2 3 4),那么我们可以达到 (1 4 2 3), (3 1 2 4) 一步完成。我们需要判断是否可以使用此操作对完整数组进行排序。
例子 :
Input : arr[] = [1, 3, 4, 2]
Output : Yes
Possible by below rotations,
[1, 3, 4, 2] -> [1, 4, 2, 3] ->
[1, 2, 3, 4]
Input : arr[] = [1, 2, 4, 3]
Output : No
Not possible to sort above array by any 3
size subarray rotation.
假设我们有一个子数组 [A[i] A[i+1] A[i+2]]。旋转一圈后,我们得到 [A[i+2], A[i], A[i+1]]
如果我们观察旋转前后的反转,我们可以看到反转的奇偶性没有改变,即如果 [A[i] A[i+1] A[i+2]] 有偶数个反转 [A[i+2] ] A[i] A[i+1]] 将有偶数反转。奇数反转也是如此。由于 A[i+2] 的移动,反转要么增加 2,要么减少 2,或者保持不变,即它们的奇偶性不会改变。
观察上述事实后,我们可以说,如果初始数组配置有偶数次反转,则可以使它们为零,使数组完全排序,否则不会。我们使用基于归并排序的方法来计算反转。得到反转次数后,我们可以很容易地检查反转的奇偶性,并判断是否可以对数组进行排序。
C++
// C++ program to check whether we can sort
// given array using 3 size subarray rotation
// or not
#include
using namespace std;
/* This function merges two sorted arrays and
returns inversion count in the arrays.*/
int merge(int arr[], int temp[], int left,
int mid, int right)
{
int i, j, k;
int inv_count = 0;
i = left; /* i is index for left subarray*/
j = mid; /* j is index for right subarray*/
k = left; /* k is index for resultant merged
subarray*/
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] <= arr[j])
temp[k++] = arr[i++];
else
{
temp[k++] = arr[j++];
/* this is tricky -- see above
explanation/diagram for merge()*/
inv_count = inv_count + (mid - i);
}
}
/* Copy the remaining elements of left subarray
(if there are any) to temp */
while (i <= mid - 1)
temp[k++] = arr[i++];
/* Copy the remaining elements of right subarray
(if there are any) to temp*/
while (j <= right)
temp[k++] = arr[j++];
/* Copy back the merged elements to original
array */
for (i = left; i <= right; i++)
arr[i] = temp[i];
return inv_count;
}
/* An auxiliary recursive function that sorts
the input array and returns the number of
inversions in the array. */
int _mergeSort(int arr[], int temp[], int left,
int right)
{
int mid, inv_count = 0;
if (right > left)
{
/* Divide the array into two parts and
call _mergeSortAndCountInv() for each
of the parts */
mid = (right + left)/2;
/* Inversion count will be sum of inversions
in left-part, right-part and number of
inversions in merging */
inv_count = _mergeSort(arr, temp, left,
mid);
inv_count += _mergeSort(arr, temp, mid+1,
right);
/* Merge the two parts */
inv_count += merge(arr, temp, left, mid+1,
right);
}
return inv_count;
}
/* This function sorts the input array and returns the
number of inversions in the array */
int mergeSort(int arr[], int array_size)
{
int *temp = (int *)malloc(sizeof(int)*array_size);
return _mergeSort(arr, temp, 0, array_size - 1);
}
// method returns true is array can be sorted by 3
// size subarray rotation
bool possibleSortingBy3SizeSubarray(int arr[], int N)
{
int numberOfInversion = mergeSort(arr, N);
// if number of inversions are even then only
// we can sort the array
return (numberOfInversion % 2 == 0);
}
// Driver code to test above methods
int main()
{
int arr[] = {1, 3, 4, 2};
int N = sizeof(arr) / sizeof(int);
possibleSortingBy3SizeSubarray(arr, N)?
cout << "Yes\n" : cout << "No\n";
}
Java
// Java program to check whether we can sort
// given array using 3 size subarray rotation
// or not
import java.io.*;
class GFG
{
/* This function merges two sorted arrays and
returns inversion count in the arrays.*/
public static int merge(int[] arr, int left, int mid, int right)
{
int[] temp = new int[arr.length];
int inv_count = 0;
int i = left; /* i is index for left subarray*/
int j = mid; /* j is index for right subarray*/
int k = left; /* k is index for resultant merged
subarray*/
while((i <= mid-1) && (j <= right))
{
if(arr[i] <= arr[j])
{
temp[k++] = arr[i];
i++;
}
else
{
temp[k++] = arr[j];
j++;
/* this is tricky -- see above
explanation/diagram for merge()*/
inv_count = inv_count + (mid-i);
}
}
/* Copy the remaining elements of left subarray
(if there are any) to temp */
while(i <= (mid-1))
temp[k++] = arr[i++];
/* Copy the remaining elements of right subarray
(if there are any) to temp*/
while(j <= right)
temp[k++] = arr[j++];
/* Copy back the merged elements to original
array */
for (int l = left; l <= right; l++)
arr[l] = temp[l];
return inv_count;
}
/* An auxiliary recursive function that sorts
the input array and returns the number of
inversions in the array. */
public static int _mergeSort(int[] arr, int left, int right)
{
int mid, inv_count = 0;
if(left < right)
{
/* Divide the array into two parts and
call _mergeSortAndCountInv() for each
of the parts */
mid = (left + right)/2;
/* Inversion count will be sum of inversions
in left-part, right-part and number of
inversions in merging */
inv_count = _mergeSort(arr, left, mid);
inv_count += _mergeSort(arr, mid+1, right);
inv_count += merge(arr, left, mid+1, right);
}
return inv_count;
}
/* This function sorts the input array and returns the
number of inversions in the array */
public static int mergeSort(int[] arr, int N)
{
return _mergeSort(arr, 0, N-1);
}
public static boolean possibleSortingBy3SizeSubarray(int arr[], int N)
{
int numberOfInversion = mergeSort(arr, N);
// if number of inversions are even then only
// we can sort the array
return (numberOfInversion % 2 == 0);
}
// Driver code to test above methods
public static void main (String[] args)
{
int arr[] = {1, 3, 4, 2};
int N = arr.length;
if(possibleSortingBy3SizeSubarray(arr, N))
System.out.println( "Yes");
else
System.out.println("No");
}
}
Python3
# Python3 program to check whether we can sort
# given array using 3 size subarray rotation or not
# This function merges two sorted arrays and
# returns inversion count in the arrays.
def merge(arr, temp, left, mid, right):
# i is index for left subarray
# j is index for right subarray
# k is index for resultant merged subarray
i, j, k, inv_count = left, mid, left, 0
while (i <= mid - 1) and (j <= right):
if arr[i] <= arr[j]:
temp[k] = arr[i]
k, i = k + 1, i + 1
else:
temp[k] = arr[j]
k, j = k + 1, j + 1
# This is tricky -- see above
# explanation/diagram for merge()
inv_count = inv_count + (mid - i)
# Copy the remaining elements of left
# subarray (if there are any) to temp
while i <= mid - 1:
temp[k] = arr[i]
k, i = k + 1, i + 1
# Copy the remaining elements of right
# subarray (if there are any) to temp
while j <= right:
temp[k] = arr[j]
k, j = k + 1, j + 1
# Copy back the merged elements
# to original array
for i in range(left, right + 1):
arr[i] = temp[i]
return inv_count
# An auxiliary recursive function that
# sorts the input array and returns the
# number of inversions in the array.
def _mergeSort(arr, temp, left, right):
inv_count = 0
if right > left:
# Divide the array into two parts
# and call _mergeSortAndCountInv()
# for each of the parts
mid = (right + left) // 2
# Inversion count will be sum of
# inversions in left-part, right-part
# and number of inversions in merging
inv_count = _mergeSort(arr, temp, left, mid)
inv_count += _mergeSort(arr, temp, mid + 1, right)
# Merge the two parts
inv_count += merge(arr, temp, left, mid + 1, right)
return inv_count
# This function sorts the input array and
# returns the number of inversions in the array
def mergeSort(arr, array_size):
temp = [None] * array_size
return _mergeSort(arr, temp, 0, array_size - 1)
# method returns true is array can be
# sorted by 3 size subarray rotation
def possibleSortingBy3SizeSubarray(arr, N):
numberOfInversion = mergeSort(arr, N)
# if number of inversions are even
# then only we can sort the array
return (numberOfInversion % 2 == 0)
# Driver Code
if __name__ == "__main__":
arr = [1, 3, 4, 2]
N = len(arr)
if possibleSortingBy3SizeSubarray(arr, N):
print("Yes")
else:
print("No")
# This code is contributed by Rituraj Jain
C#
// C# program to check whether we
// can sort given array using 3 size
// subarray rotation or not.
using System;
class GFG
{
/* This function merges two sorted arrays and
returns inversion count in the arrays.*/
public static int merge(int []arr, int left,
int mid, int right)
{
int []temp = new int[arr.Length];
int inv_count = 0;
/* i is index for left subarray*/
int i = left;
/* j is index for right subarray*/
int j = mid;
/* k is index for resultant merged subarray*/
int k = left;
while((i <= mid-1) && (j <= right))
{
if(arr[i] <= arr[j])
{
temp[k++] = arr[i];
i++;
}
else
{
temp[k++] = arr[j];
j++;
/* this is tricky -- see above
explanation/diagram for merge()*/
inv_count = inv_count + (mid-i);
}
}
/* Copy the remaining elements of
left subarray (if there are any)
to temp */
while(i <= (mid-1))
temp[k++] = arr[i++];
/* Copy the remaining elements of
right subarray (if there are any)
to temp*/
while(j <= right)
temp[k++] = arr[j++];
/* Copy back the merged elements
to original array */
for (int l = left; l <= right; l++)
arr[l] = temp[l];
return inv_count;
}
/* An auxiliary recursive function that sorts
the input array and returns the number of
inversions in the array. */
public static int _mergeSort(int []arr, int left,
int right)
{
int mid, inv_count = 0;
if(left < right)
{
/* Divide the array into two parts and
call _mergeSortAndCountInv() for each
of the parts */
mid = (left + right)/2;
/* Inversion count will be sum of inversions
in left-part, right-part and number of
inversions in merging */
inv_count = _mergeSort(arr, left, mid);
inv_count += _mergeSort(arr, mid+1, right);
inv_count += merge(arr, left, mid+1, right);
}
return inv_count;
}
/* This function sorts the input array
and returns the number of inversions
in the array */
public static int mergeSort(int[] arr, int N)
{
return _mergeSort(arr, 0, N-1);
}
public static bool possibleSortingBy3SizeSubarray(int []arr,
int N)
{
int numberOfInversion = mergeSort(arr, N);
// if number of inversions are even
// then only we can sort the array
return (numberOfInversion % 2 == 0);
}
// Driver code to test above methods
public static void Main ()
{
int []arr = {1, 3, 4, 2};
int N = arr.Length;
if(possibleSortingBy3SizeSubarray(arr, N))
Console.Write( "Yes");
else
Console.Write("No");
}
}
// This code is contributed by nitin mittal.
Javascript
输出:
Yes