Le deuxième jour du camp d'entraînement à l'algorithme d'enregistrement aléatoire de code | 907 carrés de tableau ordonné, 209 sous-tableau avec la plus petite longueur, 59 matrice en spirale II

Liens vers des articles et des vidéos appris aujourd'hui

977 article lien: lien
977 vidéo explication lien: lien
209 article lien: lien
209 vidéo explication lien: lien
59 article lien: lien
59 vidéo explication lien: lien

977 Carré d'un tableau de nombres

Voir le titre première pensée

Étant donné que le titre consiste à renvoyer le carré de chaque nombre pour former un nouveau tableau pour un tableau d'entiers dans un ordre non décroissant , il doit également être trié dans un ordre non décroissant . Ayez les idées suivantes :

  1. Mettez d'abord au carré les éléments du tableau
  2. Le code de tri rapide des valeurs numériques
    est le suivant :
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;
    }

Réflexions après avoir lu le caprice du code

Le tri violent auquel j'ai pensé a été mentionné dans les pensées aléatoires du code, et sa complexité temporelle est O(n + nlogn), mais il existe une autre méthode avec une complexité temporelle inférieure - la méthode du double pointeur .

méthode du double pointeur

Étant donné que le tableau est ordonné (il peut contenir des nombres négatifs), la valeur maximale après le carré du tableau doit être aux deux extrémités du tableau, de sorte que la méthode du double pointeur peut être envisagée, i pointe vers la position de départ et j pointe à la position finale.

Un nouveau résultat de tableau doit être défini, dont la taille est identique à nums, de sorte que k pointe vers la position finale du tableau de résultat.

si nums[i] * nums[i] > nums[j] * nums[j]alors result[k--] = nums[i] * nums[i]
si nums[i] * nums[i] <= nums[j] * nums[j]alorsresult[k--] = nums[j] * nums[j]

Difficultés rencontrées lors de la mise en œuvre

Je vector<int> result(nums.size(), 0);ne comprends pas très bien cette phrase
, interrogez-la comme méthode d'initialisation du vecteur:


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

le code

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 Le sous-réseau avec la plus petite longueur

Voir le titre première pensée

Description du titre :
Soit un ntableau contenant des entiers positifs et un entier positif target. Trouver le plus petit sous-tableau continu
dans le tableau qui satisfait sa somme [num sl s_l≥ targetsje, soit sl + 1 s_{l+1}sl + 1, …, num sr − 1 s_{r-1}sr 1, num sr s_rsr], et renvoie sa longueur. Si aucun sous-tableau ne remplit la condition, retournez-le 0.
Voyant les sous-tableaux continus requis par le titre pour répondre aux exigences, j'ai pensé à la méthode de la fenêtre glissante .

Réflexions après avoir lu le caprice du code

L'enregistrement aléatoire de code recommande également la méthode de la fenêtre glissante .

La signification de la fenêtre glissante est d'ajuster en permanence la position de départ et la position de fin de la sous-séquence pour obtenir le résultat souhaité.

Une seule boucle for est utilisée, et l'index de cette boucle doit indiquer la position finale de la fenêtre glissante.

Alors, comment déplacer la position de départ de la fenêtre active ?

Si la valeur de la fenêtre courante est supérieure à s, la fenêtre avancera.

Difficultés rencontrées lors de la mise en œuvre

L'idée est correcte, mais il est un peu difficile de déplacer la position initiale de la fenêtre lors de l'utilisation du code.

Cette partie du code est la suivante :

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

le code

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 Matrice spirale II

Voir le titre première pensée

Description du titre :
Donnez-vous un entier positif n, générez un entier contenant 1 à n 2 n^2n2 Tous les éléments, et les éléments sont disposés dans le sens des aiguilles d'une montre dans une matrice n x ncarréematrix.
Après avoir vu cette question, j'ai pensé que la clé pour résoudre cette question est la gestion des conditions aux limites, et le principe d'invariance de boucle doit être respecté.

Réflexions après avoir lu le caprice du code

Ce qui est mis en avant dans les pensées aléatoires du code, c'est d'adhérer au principe d'invariance de boucle .

Simulez le processus de dessin d'une matrice dans le sens des aiguilles d'une montre :

  • Remplir la rangée supérieure de gauche à droite
  • Remplir la colonne de droite de haut en bas
  • Remplir la ligne décroissante de droite à gauche
  • Remplir la colonne de gauche de bas en haut

Dessinez un cercle de l'extérieur vers l'intérieur.

Dans une telle boucle, la clé du traitement est les conditions aux limites Si vous ne parcourez pas selon des règles fixes, il est facile de se perdre dans la boucle.

Par conséquent, lors du dessin de chaque côté, nous devons adhérer au principe de fermeture à gauche et d'ouverture à droite, ou d'ouverture à gauche et de fermeture à droite, afin que nous puissions dessiner selon des règles uniformes et ne pas nous perdre.

Difficultés rencontrées lors de la mise en œuvre

Il existe de nombreuses conditions à juger dans la boucle while du code . Il est recommandé de dessiner un graphique dynamique pour réfléchir au changement de conditions.
insérez la description de l'image ici

Image tirée du site Web de Carl's Code Random Thoughts

le code

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;
    }
};

Récolte aujourd'hui

1. Maîtrisez la méthode de tri de la méthode du double pointeur, vous pouvez dire au revoir avec un tri violent

2. Lors de la mise en place d'une fenêtre coulissante, tenez compte des trois points suivants :

  • Qu'y a-t-il à l'intérieur de la fenêtre ?
  • Comment déplacer la position de départ de la fenêtre ?
  • Comment déplacer la position finale de la fenêtre ?

3. Lorsque nous rencontrons le problème de la matrice en spirale, nous devons adhérer au principe d'invariance de boucle pour éviter de nous perdre dans la boucle

Le temps d'étude d'aujourd'hui est de 3 heures

Je suppose que tu aimes

Origine blog.csdn.net/m0_46555669/article/details/126999364
conseillé
Classement