📜  计算子数组中的反转

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

计算子数组中的反转

给定一个数组arr[] ,目标是计算所有子数组中的反转次数。反转是一对索引ij使得i > jarr[i] < arr[j] 。从索引xy ( x<= y)的子数组由元素的arr[x], arr[x+1], ..., arr[y]组成。数组arr[]也可以包含重复的元素。

例子:

朴素方法:一种朴素的方法是生成所有可能的子数组并计算每个子数组中的反转次数。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count the number of
// inversions in all the sub-arrays
void findSubarrayInversions(int arr[], int n)
{
 
    int inversions[n][n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            int ans = 0;
            // counting the number of inversions
            // for a subarray
            for (int x = i; x <= j; x++) {
                for (int y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << inversions[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    int n = 7;
    int arr[n] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}


Java
// Java program for the above approach
class GFG{
 
// Function to count the number of
// inversions in all the sub-arrays
static void findSubarrayInversions(int arr[], int n)
{
    int [][]inversions = new int[n][n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for(int i = 0; i < n; i++)
    {
        for(int j = i; j < n; j++)
        {
            int ans = 0;
           
            // Counting the number of inversions
            // for a subarray
            for(int x = i; x <= j; x++)
            {
                for(int y = x; y <= j; y++)
                {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for(int i = 0; i < n; i++)
    {
        for(int j = 0; j < n; j++)
        {
            System.out.print(inversions[i][j] + " ");
        }
        System.out.println();
    }
}
 
// Driver Code
public static void main(String args[])
{
     
    // Given Input
    int n = 7;
    int []arr = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}
}
 
// This code is contributed by SoumikMondal.


Python3
# Python3 program for the above approach
 
# Function to count the number of
# inversions in all the sub-arrays
def findSubarrayInversions(arr, n):
     
    inversions = [[0 for i in range(n)]
                     for j in range(n)]
                      
    # Initializing the inversion count
    # of each subarray to 0
    # inversions[i][j] will denote
    # the number of inversions
    # from index i to index j inclusive
    # Generating all subarray
    for i in range(0, n):
        for j in range(0, n):
            ans = 0
             
            # Counting the number of inversions
            # for a subarray
            for x in range(i, j + 1):
                for y in range(x, j + 1):
                    if (arr[x] > arr[y]):
                        ans += 1
                         
            # Print(ans)
            inversions[i][j] = ans
 
    # Printing the number of inversions
    # of all subarrays
    for i in range(0, n):
        for j in range(0, n):
            print(inversions[i][j], end = " ")
             
        print()
 
# Driver Code
 
# Given Input
n = 7
arr = [ 3, 6, 1, 6, 5, 3, 9 ]
 
# Function Call
findSubarrayInversions(arr, n)
 
# This code is contributed by amreshkumar3


C#
// C# program for the above approach
using System;
using System.Collections.Generic;
 
class GFG{
 
// Function to count the number of
// inversions in all the sub-arrays
static void findSubarrayInversions(int []arr, int n)
{
 
    int [,]inversions = new int[n,n];
 
    // Initializing the inversion count
    // of each subarray to 0
    // inversions[i][j] will denote
    // the number of inversions
    // from index i to index j inclusive
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            inversions[i,j] = 0;
        }
    }
 
    // Generating all subarray
    for (int i = 0; i < n; i++)
    {
        for (int j = i; j < n; j++)
        {
            int ans = 0;
           
            // counting the number of inversions
            // for a subarray
            for (int x = i; x <= j; x++) {
                for (int y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i,j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            Console.Write(inversions[i,j] + " ");
        }
        Console.WriteLine();
    }
}
 
// Driver Code
public static void Main()
{
 
    // Given Input
    int n = 7;
    int []arr = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}
}
 
// This code is contributed by ipg2016107.


Javascript


C++
// C++ program for the above approach
#include 
using namespace std;
 
// Function to count the number of
// inversions in all the sub-arrays
void findSubarrayInversions(int arr[], int n)
{
 
    int greater[n][n];
    int prefix[n][n];
    int inversions[n][n];
 
    // Initializing the arrays to 0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            greater[i][j] = 0;
            prefix[i][j] = 0;
            inversions[i][j] = 0;
        }
    }
 
    // For each pair of indices i and j
    // calculating the number of elements
    // from i to j inclusive which are
    // greater than arr[i]
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            greater[i][j] = greater[i][j - 1];
            if (arr[i] > arr[j])
                greater[i][j]++;
        }
    }
 
    // Building the prefix table.
    // Prefix[i][j] denotes the sum of
    // greater[0][j], greater[1][j] ... greater[i][j]
    for (int j = 0; j < n; j++) {
        prefix[0][j] = greater[0][j];
        for (int i = 1; i < n; i++) {
            prefix[i][j] = prefix[i - 1][j] + greater[i][j];
        }
    }
 
    // Calculating the inversion count for
    // each subarray using the prefix table
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            if (i == 0)
                inversions[i][j] = prefix[j][j];
            else
                inversions[i][j] = prefix[j][j]
                                   - prefix[i - 1][j];
        }
    }
 
    // Printing the values of the number
    // of inversions in each subarray
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << inversions[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    int n = 7;
    int arr[n] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}


Python3
# Python3 program for the above approach
 
# Function to count the number of
# inversions in all the sub-arrays
def findSubarrayInversions(arr, n):
     
    # Initializing the arrays to 0
    greater = [[0 for i in range(n)]
                  for j in range(n)]
    prefix = [[0 for i in range(n)]
                 for j in range(n)]
    inversions = [[0 for i in range(n)]
                     for j in range(n)]
 
    # For each pair of indices i and j
    # calculating the number of elements
    # from i to j inclusive which are
    # greater than arr[i]
    for i in range(0, n):
        for j in range(i + 1, n):
            greater[i][j] = greater[i][j - 1]
             
            if (arr[i] > arr[j]):
                greater[i][j] += 1
 
    # Building the prefix table.
    # Prefix[i][j] denotes the sum of
    # greater[0][j], greater[1][j] ... greater[i][j]
    for j in range(0, n):
        prefix[0][j] = greater[0][j]
        for i in range(1, n):
            prefix[i][j] = (prefix[i - 1][j] +
                            greater[i][j])
             
    # Calculating the inversion count for
    # each subarray using the prefix table
    for i in range(0, n):
        for j in range(i, n):
            if (i == 0):
                inversions[i][j] = prefix[j][j]
            else:
                inversions[i][j] = (prefix[j][j] -
                                    prefix[i - 1][j])
 
    # Printing the values of the number
    # of inversions in each subarray
    for i in range(0, n):
        for j in range(0, n):
            print(inversions[i][j], end = " ")
             
        print()
 
# Driver Code
# Given Input
n = 7
arr = [ 3, 6, 1, 6, 5, 3, 9 ]
 
# Function Call
findSubarrayInversions(arr, n)
 
# This code is contributed by amreshkumar3


Javascript


输出:
0 0 2 2 4 7 7 
0 0 1 1 3 6 6 
0 0 0 0 1 3 3 
0 0 0 0 1 3 3 
0 0 0 0 0 1 1 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0

时间复杂度: O(N 4 )
辅助空间: O(N 2 )

高效方法:上述方法可以使用此处给出的方法进行一些优化,以查找子数组中的反转次数。首先看一些观察来解决这个问题:

请按照以下步骤解决此问题:

  • 初始化数组greater[][]来存储 其中Greater[i][j]表示ij范围内大于arr[i] 的元素个数,prefix[][]存储子数组的前缀和, inversions[][]存储反转次数。
  • 使用变量i[0, N-1]范围内迭代:
    • 使用变量j[i+1, N-1]范围内迭代:
      • 更大[i][j]更新为更大[i][j-1]
      • 如果arr[i]大于arr[j],则将greater[i][j]增加1。
  • 使用变量i[0, N-1]范围内迭代:
    • 前缀 [0][j]更新为更大 [0][j]
    • 使用变量j在范围[1, N-1]中迭代,并将prefix[i][j]更新为prefix[i-1][j] + greater[i][j]。
  • 使用变量i[0, N-1]范围内迭代:
    • 使用变量j在范围[i, N-1]中迭代:
      • 如果i = 0,则将inversions[i][j]更新为prefix[j][j]
      • 否则,将inversions[i][j]更新为prefix[j][j] + prefix[i-1][j]。
  • 完成上述步骤后,打印inversions[][]数组作为答案。

下面是上述方法的实现:

C++

// C++ program for the above approach
#include 
using namespace std;
 
// Function to count the number of
// inversions in all the sub-arrays
void findSubarrayInversions(int arr[], int n)
{
 
    int greater[n][n];
    int prefix[n][n];
    int inversions[n][n];
 
    // Initializing the arrays to 0
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            greater[i][j] = 0;
            prefix[i][j] = 0;
            inversions[i][j] = 0;
        }
    }
 
    // For each pair of indices i and j
    // calculating the number of elements
    // from i to j inclusive which are
    // greater than arr[i]
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            greater[i][j] = greater[i][j - 1];
            if (arr[i] > arr[j])
                greater[i][j]++;
        }
    }
 
    // Building the prefix table.
    // Prefix[i][j] denotes the sum of
    // greater[0][j], greater[1][j] ... greater[i][j]
    for (int j = 0; j < n; j++) {
        prefix[0][j] = greater[0][j];
        for (int i = 1; i < n; i++) {
            prefix[i][j] = prefix[i - 1][j] + greater[i][j];
        }
    }
 
    // Calculating the inversion count for
    // each subarray using the prefix table
    for (int i = 0; i < n; i++) {
        for (int j = i; j < n; j++) {
            if (i == 0)
                inversions[i][j] = prefix[j][j];
            else
                inversions[i][j] = prefix[j][j]
                                   - prefix[i - 1][j];
        }
    }
 
    // Printing the values of the number
    // of inversions in each subarray
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            cout << inversions[i][j] << " ";
        }
        cout << "\n";
    }
}
 
// Driver Code
int main()
{
 
    // Given Input
    int n = 7;
    int arr[n] = { 3, 6, 1, 6, 5, 3, 9 };
 
    // Function Call
    findSubarrayInversions(arr, n);
}

Python3

# Python3 program for the above approach
 
# Function to count the number of
# inversions in all the sub-arrays
def findSubarrayInversions(arr, n):
     
    # Initializing the arrays to 0
    greater = [[0 for i in range(n)]
                  for j in range(n)]
    prefix = [[0 for i in range(n)]
                 for j in range(n)]
    inversions = [[0 for i in range(n)]
                     for j in range(n)]
 
    # For each pair of indices i and j
    # calculating the number of elements
    # from i to j inclusive which are
    # greater than arr[i]
    for i in range(0, n):
        for j in range(i + 1, n):
            greater[i][j] = greater[i][j - 1]
             
            if (arr[i] > arr[j]):
                greater[i][j] += 1
 
    # Building the prefix table.
    # Prefix[i][j] denotes the sum of
    # greater[0][j], greater[1][j] ... greater[i][j]
    for j in range(0, n):
        prefix[0][j] = greater[0][j]
        for i in range(1, n):
            prefix[i][j] = (prefix[i - 1][j] +
                            greater[i][j])
             
    # Calculating the inversion count for
    # each subarray using the prefix table
    for i in range(0, n):
        for j in range(i, n):
            if (i == 0):
                inversions[i][j] = prefix[j][j]
            else:
                inversions[i][j] = (prefix[j][j] -
                                    prefix[i - 1][j])
 
    # Printing the values of the number
    # of inversions in each subarray
    for i in range(0, n):
        for j in range(0, n):
            print(inversions[i][j], end = " ")
             
        print()
 
# Driver Code
# Given Input
n = 7
arr = [ 3, 6, 1, 6, 5, 3, 9 ]
 
# Function Call
findSubarrayInversions(arr, n)
 
# This code is contributed by amreshkumar3

Javascript


输出:
0 0 2 2 4 7 7 
0 0 1 1 3 6 6 
0 0 0 0 1 3 3 
0 0 0 0 1 3 3 
0 0 0 0 0 1 1 
0 0 0 0 0 0 0 
0 0 0 0 0 0 0

时间复杂度: O(N 2 )
空间复杂度: O(N 2 )

笔记-

  • 通过在更大[][] 表之上构建前缀[][] 表可以节省一些空间,但顺序仍然保持不变。
  • 如果您想找到所有子数组中反转的确切计数,因为子数组的数量始终为 O(N^2),因此不可能比 O(N^2) 执行得更好。