Contando inversiones en un subarreglo

Dada una array arr[] , el objetivo es contar el número de inversiones en todas las sub-arrays. Una inversión es un par de índices i y j tales que i > j y arr[i] < arr[j] . Un subarreglo del índice x al y (x<= y) consiste en el elemento arr[x], arr[x+1], …, arr[y] . La array arr[] también puede contener elementos repetidos.

Ejemplos:

Entrada : arr[] = {3, 6, 1, 6, 5, 3, 9}
Salida
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
Explicación
el elemento en la i-ésima fila y la j-ésima columna de la salida indica el número de inversiones del índice i al j (inclusivo). Considere i = 1 y j = 4 (suponiendo indexación basada en 0), el número de inversiones en el subarreglo {6, 1, 6, 5} es 3. Los pares de elementos son (6, 1), (6, 5) y (6, 5) (del segundo 6). 

Entrada : arr[] = {3, 2, 1}
Salida :  
0 1 3
0 0 1
0 0 0
Explicación
Del índice 0 al 1 hay 1 inversión, del índice 2 al 3 hay 1 inversión y del índice 0 al 2 hay 3 inversiones. La i-ésima fila y la j-ésima columna de la salida es 0 si i >= j.

Enfoque ingenuo: un enfoque ingenuo es generar todos los subconjuntos posibles y contar el número de inversiones en cada uno de los subconjuntos. 

A continuación se muestra la implementación del enfoque anterior:

C++

// C++ program for the above approach
#include <bits/stdc++.h>
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

<script>
 
// JavaScript program for the above approach
 
// Function to count the number of
// inversions in all the sub-arrays
function findSubarrayInversions(arr, n) {
 
    let inversions = new Array(n).fill(0).map(() => new Array(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 (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            inversions[i][j] = 0;
        }
    }
 
    // Generating all subarray
    for (let i = 0; i < n; i++) {
        for (let j = i; j < n; j++) {
            let ans = 0;
            // counting the number of inversions
            // for a subarray
            for (let x = i; x <= j; x++) {
                for (let y = x; y <= j; y++) {
                    if (arr[x] > arr[y])
                        ans++;
                }
            }
 
            inversions[i][j] = ans;
        }
    }
 
    // Printing the number of inversions
    // of all subarrays
    for (let i = 0; i < n; i++) {
        for (let j = 0; j < n; j++) {
            document.write(inversions[i][j] + " ");
        }
        document.write("<br>");
    }
}
 
// Driver Code
 
 
// Given Input
let n = 7;
let arr = [3, 6, 1, 6, 5, 3, 9];
 
// Function Call
 
findSubarrayInversions(arr, n);
 
</script>
Producción: 

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

 

Complejidad de Tiempo: O(N 4 )
Espacio Auxiliar: O(N 2

Enfoque eficiente: el método anterior se puede optimizar un poco usando el método que se proporciona aquí para encontrar el número de inversiones en un subarreglo. Primero vea algunas observaciones para resolver este problema:

Primero cree una array 2d mayor[][] , donde mayor[i][j] denota el número de elementos en el rango i a j que son mayores que arr[i]. Itere sobre la array y para cada elemento, encuentre el número de elementos a su derecha que son menores que el elemento. Esto se puede hacer usando un enfoque ingenuo en O (N ^ 2).  Ahora, para encontrar el número de inversiones en un rango, digamos de x a y, la respuesta será mayor[x][y] + mayor[x+1][y] + … + mayor[y-1][y] + mayor [y][y].

Con la tabla mayor[][] , este valor se puede calcular en O(n) para cada subarreglo, lo que da como resultado una complejidad de O(n^3) . (Hay O(n^2) subarreglo, y toma O(n) tiempo para calcular el número de inversiones en cada subarreglo). Para encontrar este valor en O(1) cada vez, cree una tabla de suma de prefijos a partir de la tabla mayor[][] , donde prefijo[i][j] denota el valor de mayor[0][j] + mayor[1][j ] + … + mayor[i][j]. Esta tabla también se puede construir en tiempo O(N^2) . Ahora la respuesta para cada subarreglo de x a y (inclusive) seríaprefijo[y][y] – prefijo[x-1][y] si x >= 1 y prefijo[y][y] si x = 0.

Siga el siguiente paso para resolver este problema:

  • Inicializar arreglos mayor[][] para almacenar donde mayor[i][j] denota el número de elementos en el rango i a j que son mayores que arr[i], prefijo[][] para almacenar la suma de prefijos para el subarreglo y inversiones[][] para almacenar el número de inversiones.
  • Iterar en un rango [0, N-1] usando una variable i :
    • Iterar en un rango [i+1, N-1] usando una variable j:
      • Actualizar mayor[i][j] como mayor[i][j-1]
      • Si arr[i] es mayor que arr[j], entonces Incrementa mayor[i][j] en 1.
  • Iterar en un rango [0, N-1] usando una variable i :
    • Actualizar prefijo[0][j] como mayor[0][j]
    • Iterar en un rango [1, N-1] usando una variable j y actualizar el prefijo [i] [j] como prefijo [i-1] [j] + mayor [i] [j].
  • Iterar en un rango [0, N-1] usando una variable i :
    • Iterar en un rango [i, N-1] usando una variable j:
      • Si i = 0, actualice las inversiones [i] [j] como prefijo [j] [j]
      • De lo contrario, actualice inversiones[i][j] como prefijo[j][j] + prefijo[i-1][j].
  • Después de completar los pasos anteriores, imprima la array de inversiones[][] como respuesta.

A continuación se muestra la implementación del enfoque anterior:

C++

// C++ program for the above approach
#include <bits/stdc++.h>
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

<script>
// Javascript program for the above approach
 
// Function to count the number of
// inversions in all the sub-arrays
function findSubarrayInversions(arr, n) {
  let greater = new Array(n).fill(0).map(() => new Array(n).fill(0));
  let prefix = new Array(n).fill(0).map(() => new Array(n).fill(0));
  let inversions = new Array(n).fill(0).map(() => new Array(n).fill(0));
 
  // Initializing the arrays to 0
  for (let i = 0; i < n; i++) {
    for (let 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 (let i = 0; i < n; i++) {
    for (let 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 (let j = 0; j < n; j++) {
    prefix[0][j] = greater[0][j];
    for (let 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 (let i = 0; i < n; i++) {
    for (let 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 (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      document.write(inversions[i][j] + " ");
    }
    document.write("<br>");
  }
}
 
// Driver Code
 
// Given Input
let n = 7;
let arr = [3, 6, 1, 6, 5, 3, 9];
 
// Function Call
findSubarrayInversions(arr, n);
 
// This code is contributed by saurabh_jaiswal.
</script>
Producción: 

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

 

Complejidad de tiempo: O(N 2 )
Complejidad de espacio: O(N 2 )

Notas-

  • Se puede ahorrar algo de espacio construyendo la tabla de prefijo[][] encima de la tabla mayor[][], pero el orden seguirá siendo el mismo.
  • No es posible obtener un rendimiento mejor que O(N^2) si desea encontrar el recuento exacto de inversiones en todos los subarreglos, ya que el número de subarreglos siempre es O(N^2).

Publicación traducida automáticamente

Artículo escrito por arun49804 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *