[Super detallado ~] el uso del algoritmo de doble puntero

1. Escenario de uso:

Generalmente, cuando es necesario obtener un segmento determinado de los elementos de la matriz, los punteros rápidos y lentos se pueden paralelizar.

El método de doble puntero (método de puntero rápido y lento) es muy común en la operación de matrices y listas enlazadas.Muchas preguntas de entrevista que investigan operaciones en matrices, listas enlazadas y cadenas utilizan el método de doble puntero.

2. Tipo:

Punteros rápidos y lentos, punteros de cabeza y cola, ventanas deslizantes, etc.

3. Cómo usar

(1) La j en el bucle for es equivalente a un puntero

Luego puede definir una variable global i como otro puntero y usar i++ para mover el puntero para

let i = 0
for (let j = 0; j < arr.length; j++){
    
    
    arr[i++] = arr[j]
}

(2) A veces, dos punteros se definen directamente en el bucle for

for (let i = 1, j = 0; arr[i] < arr[j]){
    
    
    
}

4. Escenarios de aplicación

(1) Eliminar elementos de la matriz

Dada una matriz nums y un valor val, debe eliminar todos los elementos cuyo valor sea igual a val en su lugar y devolver la nueva longitud de la matriz eliminada.

No use espacio de matriz adicional, debe usar solo O (1) espacio adicional y modificar la matriz de entrada en el lugar .

El orden de los elementos se puede cambiar. No necesita considerar elementos en la matriz más allá de la nueva longitud.

Idea: puntero rápido para encontrar los elementos de la nueva matriz (elementos que no son iguales a val)

El puntero lento identifica dónde la nueva matriz es actualmente capaz de agregar nuevos elementos (en realidad, sobrescribe elementos de la matriz anterior)

// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowIndex = 0;
        for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) { //一开始两个指针都指向一个元素
            if (val != nums[fastIndex]) { //一旦等于,快指针就把慢指针甩开了
                nums[slowIndex++] = nums[fastIndex]; //一开始相当于自己给自己赋值
                //一旦甩开了就是后一个给前一个赋值
            }
        }
        return slowIndex;
    }
};

(2) El cuadrado de un arreglo ordenado (arreglos en orden no decreciente, positivo y negativo)

Dada una matriz de números enteros ordenados en orden no decreciente, devuelve una nueva matriz que consiste en el cuadrado de cada número, también ordenados en orden no decreciente.

Idea: un puntero de cabeza, un puntero de cola

Compare los valores cuadrados de los elementos actualmente señalados por los dos y póngalos en el conjunto de resultados

class Solution {
public:
    vector<int> sortedSquares(vector<int>& A) {
        int k = A.size() - 1; //指向新数组,从尾部开始移动
        vector<int> result(A.size(), 0); //新数组
        for (int i = 0, j = A.size() - 1; i <= j;) { // 注意这里要i <= j,因为最后要处理两个元素
            if (A[i] * A[i] < A[j] * A[j])  {
                result[k--] = A[j] * A[j];
                j--;
            }
            else {
                result[k--] = A[i] * A[i];
                i++;
            }
        }
        return result;
    }
};

(3) El subarreglo con la longitud más pequeña

Dada una matriz que contiene n enteros positivos y un entero positivo s, encuentre el subarreglo continuo más pequeño cuya suma ≥ s en la matriz y devuelva su longitud. Devuelve 0 si no existe ningún subarreglo coincidente.

Idea: ¡La ventana deslizante también puede entenderse como una especie de método de doble puntero!

class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX;
        int sum = 0; // 滑动窗口数值之和
        int i = 0; // 滑动窗口起始位置
        int subLength = 0; // 滑动窗口的长度
        for (int j = 0; j < nums.size(); j++) {
            sum += nums[j];
            // 注意这里使用while,每次更新 i(起始位置),并不断比较子序列是否符合条件
            while (sum >= s) { //一旦和超过了目标值
                subLength = (j - i + 1); // 取子序列的长度
                result = result < subLength ? result : subLength; //如果出现了更短的,就把结果改成更短的
                sum -= nums[i++]; // 移除第一个元素。这里体现出滑动窗口的精髓之处,不断变更i(子序列的起始位置)
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};

Supongo que te gusta

Origin blog.csdn.net/m0_58768224/article/details/129797030
Recomendado
Clasificación