Método de clasificación de orden inverso versus fusión para dividir y conquistar

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 ~ midsubíndice, A [i] es mayor que A [j]
  • Entonces, para A [j] para revertir a la derecha, que se encuentra mid-ien

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;
}
262 artículos originales publicados · ganó 11 · 10 mil visitas

Supongo que te gusta

Origin blog.csdn.net/weixin_44176696/article/details/105092613
Recomendado
Clasificación