El segundo día del campo de entrenamiento del algoritmo de grabación aleatoria de código | 907 cuadrados de matriz ordenada, 209 sub-matriz con la longitud más pequeña, 59 matriz espiral II

Enlaces a artículos y videos aprendidos hoy

Enlace del artículo 977: enlace
Enlace del artículo 977: enlace
Enlace del artículo 209: enlace
Enlace del artículo 209: enlace
Enlace del artículo 59: enlace
Enlace de la explicación del vídeo 59: enlace

977 Cuadrado de una matriz de números

Ver el título primero pensado

Debido a que el título es devolver el cuadrado de cada número para formar una nueva matriz para una matriz de enteros en orden no decreciente , también se requiere que se ordene en orden no decreciente . Tenga las siguientes ideas:

  1. Primero eleva al cuadrado los elementos de la matriz.
  2. El código para la ordenación rápida de valores numéricos
    es el siguiente:
class Solution {
    
    
public:
    vector<int> sortedSquares(vector<int>& nums) {
    
    
        for (int i = 0; i < nums.size(); i++) {
    
    
            nums[i] *= nums[i];
        }
        sort(nums.begin(), nums.end()); // 快速排序
        return nums;
    }

Pensamientos después de leer el código capricho.

La clasificación violenta en la que pensé se mencionó en los pensamientos aleatorios del código, y su complejidad de tiempo es O (n + nlogn), pero hay otro método con menor complejidad de tiempo: el método de doble puntero .

método de doble puntero

Debido a que la matriz está ordenada (puede contener números negativos), el valor máximo después del cuadrado de la matriz debe estar en ambos extremos de la matriz, por lo que se puede considerar el método de doble puntero, i apunta a la posición inicial y j apunta a la posición final.

Es necesario definir un nuevo resultado de matriz, cuyo tamaño sea el mismo que nums, de modo que k apunte a la posición final de la matriz de resultados.

si nums[i] * nums[i] > nums[j] * nums[j]entonces result[k--] = nums[i] * nums[i]
si nums[i] * nums[i] <= nums[j] * nums[j]entoncesresult[k--] = nums[j] * nums[j]

Dificultades encontradas durante la implementación

No vector<int> result(nums.size(), 0);entiendo muy bien esta oración
, consulta esto como el método para inicializar el vector:


vector<int> result(nums.size(), 0); //初始化,第一个参数是数目,第二个参数是要初始化的值

el código

class Solution {
    
    
public:
    vector<int> sortedSquares(vector<int>& nums) {
    
    
        vector<int> result(nums.size(), 0);
        int k= nums.size()-1;
        for(int i = 0,j = nums.size()-1;i <= j;){
    
    
            if(nums[i] * nums[i] > nums[j] * nums[j]){
    
    
                result[k--] = nums[i] * nums[i];
                i++;
            }
            else{
    
    
                result[k--] = nums[j] * nums[j];
                j--;
            }
        }
        return result;
    }
};

209 El subarreglo con la longitud más pequeña

Ver el título primero pensado

Descripción del título:
Dada una nmatriz que contiene números enteros positivos y un número entero positivo target. Encuentre el subarreglo continuo más pequeño
en el arreglo que satisface su suma [num sl s_l≥ targetsyo, ya sea sl + 1 s_{l+1}sl + 1, …, número sr − 1 s_{r-1}sr 1, núm sr s_rsr], y devuelve su longitud. Si no hay un subarreglo que cumpla la condición, devuélvelo 0.
Al ver los subconjuntos continuos requeridos por el título para cumplir con los requisitos, pensé en el método de la ventana deslizante .

Pensamientos después de leer el código capricho.

La grabación de código aleatorio también recomienda el método de ventana deslizante .

El significado de la ventana deslizante es ajustar continuamente la posición inicial y la posición final de la subsecuencia para obtener el resultado que queremos.

Solo se usa un bucle for, y el índice de este bucle debe indicar la posición final de la ventana deslizante.

Entonces, ¿cómo mover la posición inicial de la ventana activa?

Si el valor de la ventana actual es mayor que s, la ventana avanzará.

Dificultades encontradas durante la implementación

La idea es correcta, pero es un poco difícil mover la posición inicial de la ventana cuando se opera el código.

Esta parte del código es la siguiente:

while (sum >= s) {
    
    
	subLength = (j - i + 1); // 取子序列的长度
 	result = result < subLength ? result : subLength;
	sum -= nums[i++]; //这里体现了滑动窗口的精髓之处,不断变更i(子序列的起始位置)

el código

class Solution {
    
    
public:
    int minSubArrayLen(int target, 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 (sum >= target){
    
    
                subLength = (j - i + 1);
                result = result < subLength ? result : subLength;
                sum -= nums[i++];
            }
        }
        return result == INT32_MAX ? 0 : result;
    }
};

59 Matriz Espiral II

Ver el título primero pensado

Descripción del título:
Darle un número entero positivo n, generar un número entero que contenga 1 a n 2 n^2norte2 Todos los elementos, y los elementos están dispuestos en el sentido de las agujas del reloj en una matriz n x ncuadradamatrix.
Después de ver esta pregunta, pensé que la clave para resolver esta pregunta es el manejo de las condiciones de contorno, y se debe cumplir el principio de invariancia de bucle.

Pensamientos después de leer el código capricho.

Lo que se enfatiza en los pensamientos aleatorios del código es adherirse al principio de invariancia de bucle .

Simule el proceso de dibujar una matriz en el sentido de las agujas del reloj:

  • Llene la fila superior de izquierda a derecha
  • Rellene la columna derecha de arriba a abajo
  • Rellenar fila descendente de derecha a izquierda
  • Rellene la columna izquierda de abajo hacia arriba

Dibuja en un círculo de afuera hacia adentro.

En un bucle de este tipo, la clave del procesamiento son las condiciones de contorno Si no se recorre de acuerdo con reglas fijas, es fácil perderse en el bucle.

Por lo tanto, al dibujar cada lado, debemos adherirnos al principio de cerrado a la izquierda y abierto a la derecha, o abierto a la izquierda y cerrado a la derecha, para que podamos dibujar de acuerdo con reglas uniformes y no perdernos.

Dificultades encontradas durante la implementación

Hay muchas condiciones para ser juzgadas en el bucle while en el código.Se recomienda dibujar un gráfico dinámico para pensar en el cambio de condiciones.
inserte la descripción de la imagen aquí

Imagen del sitio web de Carl's Code Random Thoughts

el código

class Solution {
    
    
public:
    vector<vector<int>> generateMatrix(int n) {
    
    
        vector<vector<int>> res(n, vector<int>(n, 0)); // 使用vector定义一个二维数组
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int loop = n / 2; // 每个圈循环几次,例如n为奇数3,那么loop = 1 只是循环一圈,矩阵中间的值需要单独处理
        int mid = n / 2; // 矩阵中间的位置,例如:n为3, 中间的位置就是(1,1),n为5,中间位置为(2, 2)
        int count = 1; // 用来给矩阵中每一个空格赋值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j;
        while (loop --) {
    
    
            i = startx;
            j = starty;

            // 下面开始的四个for就是模拟转了一圈
            // 模拟填充上行从左到右(左闭右开)
            for (j = starty; j < n - offset; j++) {
    
    
                res[startx][j] = count++;
            }
            // 模拟填充右列从上到下(左闭右开)
            for (i = startx; i < n - offset; i++) {
    
    
                res[i][j] = count++;
            }
            // 模拟填充下行从右到左(左闭右开)
            for (; j > starty; j--) {
    
    
                res[i][j] = count++;
            }
            // 模拟填充左列从下到上(左闭右开)
            for (; i > startx; i--) {
    
    
                res[i][j] = count++;
            }

            // 第二圈开始的时候,起始位置要各自加1, 例如:第一圈起始位置是(0, 0),第二圈起始位置是(1, 1)
            startx++;
            starty++;

            // offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }

        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) {
    
    
            res[mid][mid] = count;
        }
        return res;
    }
};

cosecha hoy

1. Domina el método de clasificación del método de doble puntero, puedes decir adiós con clasificación violenta

2. Al implementar una ventana corrediza, considere los siguientes tres puntos:

  • ¿Qué hay dentro de la ventana?
  • ¿Cómo mover la posición inicial de la ventana?
  • ¿Cómo mover la posición final de la ventana?

3. Al encontrar el problema de la matriz en espiral, debemos adherirnos al principio de invariancia del ciclo para evitar perdernos en el ciclo.

El tiempo de estudio de hoy es de 3 horas.

Supongo que te gusta

Origin blog.csdn.net/m0_46555669/article/details/126999364
Recomendado
Clasificación