📌  相关文章
📜  可以使用大小为 3 的子数组旋转进行排序

📅  最后修改于: 2022-05-13 01:57:47.721000             🧑  作者: Mango

可以使用大小为 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