75. Clasificación de colores
Dada una matriz de n elementos que contengan rojo, blanco y azul, ordénelos en su lugar para que los elementos del mismo color estén adyacentes y dispuestos en el orden de rojo, blanco y azul.
En esta pregunta, usamos los números enteros 0, 1 y 2 para representar el rojo, el blanco y el azul, respectivamente.
Nota:
No puede utilizar la función de clasificación en el código base para resolver este problema.
Ejemplo:
Entrada: [2,0,2,1,1,0]
Salida: [0,0,1,1,2,2]
Avanzado:Una solución intuitiva es utilizar un algoritmo de escaneo de dos pasos para contar y clasificar.
Primero, calcule iterativamente el número de elementos 0, 1 y 2, y luego vuelva a escribir la matriz actual de acuerdo con el orden de 0, 1 y 2.
¿Puede pensar en un algoritmo de escaneo de un solo paso que use solo espacio constante?
Solución 1: Primero doble puntero, introduzca el tercer puntero cuando no se mueva
class Solution {
public:
void sortColors(vector<int>& nums) {
int len = nums.size();
if (len < 2)
return;
int left = 0, right = len-1;
while (left < right) {
if (nums[left] == 0) { //先两边符合条件的数值
++left;
continue;
} else if (nums[right] == 2) {
--right;
continue;
}
if (nums[left] == 2) {
swap(nums[left], nums[right]);
--right;
} else if (nums[right] == 0) {
swap(nums[left], nums[right]);
++left;
} else if (nums[left] == 1 && nums[right] == 1) { //双指针寸步难行
int mid = left+1; //引入第三指针
while (mid < right && nums[mid] == 1) //找中间不符合条件的数值
++mid;
if (mid == right)
return;
if (nums[mid] == 0) {
swap(nums[left], nums[mid]);
++left;
} else {
swap(nums[right], nums[mid]);
--right;
}
}
}
}
};
La idea de este método es relativamente simple y el valor es relativamente estable . Los 2 últimos están siempre en el último lado y no se cambiarán. Y solo cuando sea necesario (el límite del intervalo es la 1 en punto) introduzca el tercer puntero auxiliar, sin mantener los tres punteros todo el tiempo, la operación es relativamente simple y el pensamiento es relativamente claro.
Cuando hay 1 a la derecha y muchos 1 a la izquierda, con un poco de 0/2 en el medio, el algoritmo introducirá con frecuencia el tercer puntero, y el tercer puntero atravesará repetidamente desde el límite izquierdo 1 al derecho.
Solución 2: tres punteros directos
class Solution {
public:
void sortColors(vector<int>& nums) {
int len = nums.size();
if (len < 2)
return;
int left = 0, cur = 0, right = len-1;
while (cur <= right) { //需要同步跟新left, 所以有等号
if (nums[cur] == 0) {
if (left != cur)
swap(nums[left], nums[cur]);
++left;
++cur; //从前往后,一步为0可以往下走
} else if (nums[cur] == 2) {
if (right != cur)
swap(nums[right], nums[cur]);
--right;
//++cur; //cur不能往前走,从后换到当前的值不知道是0/1/2
} else {
++cur; //当cur指的数为1时,会落下left指向第一个为1的数
}
}
}
};
Esta solución siempre mantiene tres punteros y el algoritmo no tiene estabilidad. Incluso si el valor al final cumple con las condiciones, se cambiará a cur, y luego el 2 encontrado al principio se cambiará al final La estabilidad del valor es equivalente a una inversión de orden.
El algoritmo es peor cuando la matriz original tiene 2 al principio y los últimos 2 están aproximadamente en orden.