给定一个数组arr [] ,任务是找到该数组的总有效反转计数。如果arr [i]> 2 * arr [j]且i
例子:
Input: arr[] = { 1, 20, 6, 4, 5 }
Output: 3
Significant inversion pair are (20, 6), (20, 5) and (20, 4).
Input: arr[] = { 1, 20 }
Output: 0
先决条件:计算倒数
方法:
- 查找倒置的基本思想将基于上述前提,并使用修改后的合并排序的分而治之方法。
- 可以计算出左半部分和右半部分的显着倒置次数。用索引(i,j)包括显着倒置的计数,以使i在左半部分,而j在右半部分,然后将所有三个数相加以获得总的显着倒置计数。
- 可以修改上述链接中使用的方法,以在合并步骤中执行左半边和右半边的两次遍历。在第一遍中,计算合并数组中有效反转计数的数量。对于arr [i]> 2 * arr [j],如果在左数组中的任何索引i,则在左数组中的第i个索引左侧的所有元素也将导致显着的反转计数。增量j。否则增加i。
- 第二遍将是构造合并数组。这里需要两次通过,因为在正常的反转计数中,两次通过会将i和j移动到相同的点,因此可以合并,但是在这种情况下不正确。
下面是上述方法的实现:
C++
// C++ implementation of the approach
#include
using namespace std;
int _mergeSort(int arr[], int temp[], int left, int right);
int merge(int arr[], int temp[], int left, int mid, int right);
// Function that sorts the input array
// and returns the number of inversions
// in the array
int mergeSort(int arr[], int array_size)
{
int temp[array_size];
return _mergeSort(arr, temp, 0, array_size - 1);
}
// 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 the
// inversions in the left-part, the right-part
// and the 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;
}
// Function that merges the two sorted arrays
// and returns the 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 is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// First pass to count number
// of significant inversions
while ((i <= mid - 1) && (j <= right)) {
if (arr[i] > 2 * arr[j]) {
inv_count += (mid - i);
j++;
}
else {
i++;
}
}
// i is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// Second pass to merge the two sorted arrays
while ((i <= mid - 1) && (j <= right)) {
if (arr[i] <= arr[j]) {
temp[k++] = arr[i++];
}
else {
temp[k++] = arr[j++];
}
}
// Copy the remaining elements of the left
// subarray (if there are any) to temp
while (i <= mid - 1)
temp[k++] = arr[i++];
// Copy the remaining elements of the right
// subarray (if there are any) to temp
while (j <= right)
temp[k++] = arr[j++];
// Copy back the merged elements to
// the original array
for (i = left; i <= right; i++)
arr[i] = temp[i];
return inv_count;
}
// Driver code
int main()
{
int arr[] = { 1, 20, 6, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << mergeSort(arr, n);
return 0;
}
Java
// Java implementation of the above approach
class GFG
{
// Function that sorts the input array
// and returns the number of inversions
// in the array
static int mergeSort(int arr[], int array_size)
{
int temp[] = new int[array_size];
return _mergeSort(arr, temp, 0, array_size - 1);
}
// Recursive function that sorts the input
// array and returns the number of
// inversions in the array
static 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 the
// inversions in the left-part, the right-part
// and the 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;
}
// Function that merges the two sorted arrays
// and returns the inversion count in the arrays
static int merge(int arr[], int temp[], int left,
int mid, int right)
{
int i, j, k;
int inv_count = 0;
// i is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// First pass to count number
// of significant inversions
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] > 2 * arr[j])
{
inv_count += (mid - i);
j++;
}
else
{
i++;
}
}
// i is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// Second pass to merge the two sorted arrays
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] <= arr[j])
{
temp[k++] = arr[i++];
}
else
{
temp[k++] = arr[j++];
}
}
// Copy the remaining elements of the left
// subarray (if there are any) to temp
while (i <= mid - 1)
temp[k++] = arr[i++];
// Copy the remaining elements of the right
// subarray (if there are any) to temp
while (j <= right)
temp[k++] = arr[j++];
// Copy back the merged elements to
// the original array
for (i = left; i <= right; i++)
arr[i] = temp[i];
return inv_count;
}
// Driver code
public static void main (String[] args)
{
int arr[] = { 1, 20, 6, 4, 5 };
int n = arr.length;
System.out.println(mergeSort(arr, n));
}
}
// This code is contributed by AnkitRai01
Python3
# Python3 implementation of the approach
# Function that sorts the input array
# and returns the number of inversions
# in the array
def mergeSort(arr, array_size):
temp = [0 for i in range(array_size)]
return _mergeSort(arr, temp, 0,
array_size - 1)
# Recursive function that sorts the input
# array and returns the number of
# inversions in the array
def _mergeSort(arr, temp, left, right):
mid, inv_count = 0, 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 the
# inversions in the left-part, the right-part
# and the 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
# Function that merges the two sorted arrays
# and returns the inversion count in the arrays
def merge(arr, temp, left,mid, right):
inv_count = 0
# i is the index for the left subarray
i = left
# j is the index for the right subarray
j = mid
# k is the index for the resultant
# merged subarray
k = left
# First pass to count number
# of significant inversions
while ((i <= mid - 1) and (j <= right)):
if (arr[i] > 2 * arr[j]):
inv_count += (mid - i)
j += 1
else:
i += 1
# i is the index for the left subarray
i = left
# j is the index for the right subarray
j = mid
# k is the index for the resultant
# merged subarray
k = left
# Second pass to merge the two sorted arrays
while ((i <= mid - 1) and (j <= right)):
if (arr[i] <= arr[j]):
temp[k] = arr[i]
i, k = i + 1, k + 1
else:
temp[k] = arr[j]
k, j = k + 1, j + 1
# Copy the remaining elements of the left
# subarray (if there are any) to temp
while (i <= mid - 1):
temp[k] = arr[i]
i, k = i + 1, k + 1
# Copy the remaining elements of the right
# subarray (if there are any) to temp
while (j <= right):
temp[k] = arr[j]
j, k = j + 1, k + 1
# Copy back the merged elements to
# the original array
for i in range(left, right + 1):
arr[i] = temp[i]
return inv_count
# Driver code
arr = [1, 20, 6, 4, 5]
n = len(arr)
print(mergeSort(arr, n))
# This code is contributed by Mohit Kumar
C#
// C# implementation of the above approach
using System;
class GFG
{
// Function that sorts the input array
// and returns the number of inversions
// in the array
static int mergeSort(int []arr,
int array_size)
{
int []temp = new int[array_size];
return _mergeSort(arr, temp, 0,
array_size - 1);
}
// Recursive function that sorts the input
// array and returns the number of
// inversions in the array
static 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 the
// inversions in the left-part, the right-part
// and the 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;
}
// Function that merges the two sorted arrays
// and returns the inversion count in the arrays
static int merge(int []arr, int []temp, int left,
int mid, int right)
{
int i, j, k;
int inv_count = 0;
// i is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// First pass to count number
// of significant inversions
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] > 2 * arr[j])
{
inv_count += (mid - i);
j++;
}
else
{
i++;
}
}
// i is the index for the left subarray
i = left;
// j is the index for the right subarray
j = mid;
// k is the index for the resultant
// merged subarray
k = left;
// Second pass to merge the two sorted arrays
while ((i <= mid - 1) && (j <= right))
{
if (arr[i] <= arr[j])
{
temp[k++] = arr[i++];
}
else
{
temp[k++] = arr[j++];
}
}
// Copy the remaining elements of the left
// subarray (if there are any) to temp
while (i <= mid - 1)
temp[k++] = arr[i++];
// Copy the remaining elements of the right
// subarray (if there are any) to temp
while (j <= right)
temp[k++] = arr[j++];
// Copy back the merged elements to
// the original array
for (i = left; i <= right; i++)
arr[i] = temp[i];
return inv_count;
}
// Driver code
public static void Main ()
{
int []arr = { 1, 20, 6, 4, 5 };
int n = arr.Length;
Console.WriteLine(mergeSort(arr, n));
}
}
// This code is contributed by anuj_67..
输出:
3