Introducción de par inverso
Si hay un número entero positivo i, j tal que 1 ≤ i <j ≤ ny A [i]> A [j], entonces el par ordenado <A [ifont>, A [jfont>> se llama par inverso de A, y Llamado el número de orden inverso.
Resolver el número de pares inversos en una matriz
De hecho, es encontrar un gran número con un pequeño subíndice, así que no hablemos primero de la violencia, la violencia es obviamente O (n 2 ), 8 Taihang
int unseq(vector<int> &nums)
{
int cnt = 0;
for(int i=0; i<nums.size(); i++)
for(int j=i+1; j<nums.size(); j++)
if(nums[i]>nums[j]) cnt++;
return cnt;
}
Divide y conquista el pensamiento: ordena por fusión
Para el número de pares en orden inverso en la matriz, divida la matriz en intervalos [l, mid]
AND [mid+1, r]
, y el problema puede descomponerse en subproblemas:
- Subarreglo
[l, mid]
revertir el número lcnt [mid+1, r]
Número de par de orden inverso de sub-array rcnt- A [i] está a la izquierda, A [j] está a la derecha y el par de <i, j> de A [i]> A [j]
Las preguntas 1 y 2 pueden resolverse recursivamente, entonces la clave es cómo encontrar la pregunta 3, es decir
Tenga en cuenta que al resolver el problema 12 aquí, no solo se clasifica la solución, sino también la matriz, es decir, los lados izquierdo / derecho están en un estado ordenado , entonces podemos usar el tiempo O (n) para completar la solución
- En la submatriz derecha, enumere los subíndices j de atrás hacia adelante
- En la submatriz izquierda, establezca el puntero i, al principio i apunta a la mitad
- Deslice hacia la izquierda para encontrar el primer i tal que A [i] <= A [j]
- Anterior descripción
i+1 ~ mid
subíndice, A [i] es mayor que A [j] - Entonces, para A [j] para revertir a la derecha, que se encuentra
mid-i
en
Debido a que ambos lados están ordenados, entonces para el subíndice j, porque A [j] está disminuyendo, luego A[j+1]配对的个数,同样可以运用到A[j]
hacia arriba, además, también debemos juzgar si A [j] puede cumplir con más pares de orden inverso
Aquí , se usa el orden de los dos lados de la matriz, y los resultados anteriores se usan disfrazados para ahorrar tiempo
Parece ser un doble circuito, de hecho, i, j no retrocede más de n / 2 veces, por lo que la complejidad es O (n)
Usando el tiempo O (n) para encontrar el número de pares en orden inverso, también necesitamos fusionar la matriz para facilitar la recursión previa para continuar la búsqueda
Utilice [ función inplace_merge ] para la operación de fusión
Puede tener muchos signos de interrogación aquí:
Después de ordenar, ¿no se altera el orden?
Antes de barajar el orden (clasificación), hemos obtenido el número de soluciones de las submatrices en ambos lados,
y al resolver el par inverso de la cruz , se ordenan la izquierda y la derecha, pero sus posiciones relativas no cambian , es decir, el elemento izquierdo debe estar Subarreglo a la izquierda, igual para la derecha
int unseq(vector<int> &nums, int l, int r)
{
if(l>=r || l<0 || r>=nums.size()) return 0;
int mid=(l+r)/2, cnt=0, i=mid;
int lcnt = unseq(nums, l, mid);
int rcnt = unseq(nums, mid+1, r);
for(int j=r; j>mid; j--)
{
while(i>=l && nums[j]<nums[i]) i--;
cnt += mid-i;
}
inplace_merge(nums.begin()+l, nums.begin()+mid+1, nums.begin()+r+1);
return lcnt+rcnt+cnt;
}
Código completo
#include <bits/stdc++.h>
using namespace std;
int unseq(vector<int> &nums, int l, int r)
{
if(l>=r || l<0 || r>=nums.size()) return 0;
int mid=(l+r)/2, cnt=0, i=mid;
int lcnt = unseq(nums, l, mid);
int rcnt = unseq(nums, mid+1, r);
for(int j=r; j>mid; j--)
{
while(i>=l && nums[j]<nums[i]) i--;
cnt += mid-i;
}
inplace_merge(nums.begin()+l, nums.begin()+mid+1, nums.begin()+r+1);
return lcnt+rcnt+cnt;
}
int unseq(vector<int> &nums)
{
int cnt = 0;
for(int i=0; i<nums.size(); i++)
for(int j=i+1; j<nums.size(); j++)
if(nums[i]>nums[j]) cnt++;
return cnt;
}
int main()
{
vector<int> nums{2,7,4,3,1,8,6,5};
cout<<unseq(nums)<<endl;
cout<<unseq(nums, 0, nums.size()-1)<<endl;
for(int i=0; i<nums.size(); i++) cout<<nums[i]<<" ";
cout<<endl;
return 0;
}