Notas de cepillado de Leetcode (C++) - cola de pila

Notas de cepillado de Leetcode (C++) - cola de pila

Ordene las ideas en el proceso de repasar las preguntas, resúmalas y compártalas aquí.
dirección de github: https://github.com/lvjian0706/Leetcode-solutions
El proyecto de github se creó recientemente, y el código y las ideas se cargarán uno tras otro. El código está basado en C++ y python. Al mismo tiempo, el algoritmo de clasificación básico también se clasificará y cargará.

94. Recorrido en orden de un árbol binario

Dado un árbol binario, devuelve su recorrido en orden.

Ejemplo:

Entrada : [1 , nulo, 2,3]
1

2/3

Salida: [1,3,2]
Avanzado: El algoritmo recursivo es muy simple, ¿puedes hacerlo con un algoritmo iterativo?

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:

    /*
    回溯方法
    */
    void DFS(TreeNode* root, vector<int> &ans){
    
    
        if(!root) return;
        DFS(root->left, ans);
        ans.push_back(root->val);
        DFS(root->right, ans);
    }

    /*
    中序遍历,可以使用回溯思想
    */
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> ans;
        DFS(root, ans);
        return ans;
    }
};


/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
    
    
public:
    /*
    迭代方法:(使用vector和stack共同解决)
    1. 中序遍历,访问左孩子节点存到栈中;
    2. 访问结束后,pop()出栈顶元素,存到结果数组中;
    3. 将root定义为栈顶元素的右孩子,遍历右子树;
    */
    vector<int> inorderTraversal(TreeNode* root) {
    
    
        vector<int> ans;
        stack<TreeNode*> inorder_tree;
        while(root || !inorder_tree.empty()){
    
    
            while(root){
    
    
                inorder_tree.push(root);
                root = root->left;
            }
            TreeNode* temp = inorder_tree.top();
            inorder_tree.pop();
            ans.push_back(temp->val);
            root = temp->right;
        }
        return ans;
    }
};

150. Evaluación de expresión en polaco inverso

Evalúa la expresión en notación polaca inversa.

Los operadores válidos incluyen +, -, *, /. Cada operando puede ser un número entero u otra expresión polaca inversa.

ilustrar:

La división entera mantiene solo la parte entera.
La expresión polaca inversa dada siempre es válida. En otras palabras, la expresión siempre dará como resultado un valor válido y no habrá división por cero.

Ejemplo 1:
Entrada: ["2", "1", "+", "3", " " ]
Salida: 9
Explicación: Esta fórmula se transforma en una expresión aritmética de infijo común: ((2 + 1) * 3) = 9
Ejemplo 2:
Entrada: ["4", "13", "5", "/", "+"]
Salida: 6
Explicación: Esta fórmula se transforma en una expresión aritmética de infijo común: (4 + (13 / 5)) = 6
Ejemplo 3:
Entrada: ["10", "6", "9", "3", "+", "-11", " ", "/", "* ", "17
" , "+", "5", "+"]
Salida: 22
Explicación:
Esta fórmula se transforma en una expresión aritmética infija común:
((10 * (6 / ((9 + 3) * - 11))) + 17 ) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= (( 10 * 0) + 17 ) + 5
= (0 + 17) + 5
= 17 + 5
= 22

Expresión polaca inversa:
la expresión polaca inversa es una expresión de sufijo, el llamado sufijo significa que el operador está escrito detrás.
La fórmula comúnmente utilizada es una expresión infija, como ( 1 + 2 ) * ( 3 + 4 ).
La expresión polaca inversa de esta fórmula es ( ( 1 2 + ) ( 3 4 + ) * ).
La expresión polaca inversa tiene las siguientes dos ventajas:
la expresión no tiene ambigüedad después de quitar los corchetes, y la fórmula anterior se puede calcular de acuerdo con el orden incluso si se escribe como 1 2 + 3 4 + *.
Es adecuado para operaciones de pila: cuando se encuentra un número, se coloca en la pila; cuando se encuentra un operador, los dos números en la parte superior de la pila se extraen para el cálculo y el resultado se coloca en la pila.

class Solution {
    
    
public:
    /*
    逆波兰表达式求值:
    使用栈来存储每个数字以及当前的计算结果;为了方便定义flag标志位,使用switch语句进行判断;
    1. 当字符串长度大于1或字符串的第一个元素大于‘0’小于‘9’时,说明字符串中为数字,将string转为int后入栈;(注意处理2位数以上的数以及负数)
    2. 当字符串中存储的是运算符:将栈顶的两个元素取出后进行计算,结果重新入栈;
    3. 栈顶元素为最终结果;
    */
    int evalRPN(vector<string>& tokens) {
    
    
        stack<int> nums;
        static const int NUMBER = 1;
        static const int OPERATOR = 2;
        int flag = NUMBER;
        for(int i=0; i<tokens.size(); i++){
    
    
            string mem = tokens[i];
            if(mem.size()>1 || (mem[0]>='0' && mem[0]<='9')) flag = NUMBER;
            else flag = OPERATOR;
            switch(flag){
    
    
                case NUMBER:{
    
    
                    int j=0, temp=0;
                    if(mem[0]=='-') j++;
                    while(mem[j]>='0' && mem[j]<='9'){
    
    
                        temp = temp * 10 + mem[j] - '0';
                        j++;
                    }
                    if(mem[0]=='-') nums.push(0-temp);
                    else nums.push(temp);
                    break;
                }
                case OPERATOR:{
    
    
                    int num1 = nums.top();
                    nums.pop();
                    int num2 = nums.top();
                    nums.pop();
                    if(mem[0]=='+') nums.push(num2+num1);
                    else if(mem[0]=='-') nums.push(num2-num1);
                    else if(mem[0]=='*') nums.push(num2*num1);
                    else if(mem[0]=='/') nums.push(num2/num1);
                    break;
                }
            }
        }
        return nums.top();
    }
};

155. Pila mínima

Diseñe una pila que admita operaciones push, pop, top y que pueda recuperar el elemento más pequeño en tiempo constante.

push(x) – empuja el elemento x a la pila.
pop(): elimina el elemento en la parte superior de la pila.
top() - Obtiene el elemento superior de la pila.
getMin(): recupera el elemento más pequeño de la pila.

Ejemplo:
Entrada:
["MinStack", "push", "push", "push", "getMin", "pop", "top", "getMin"] [[],[-2],[0]
, [-3],[],[],[],[]]
Salida:
[null,null,null,null,-3,null,0,-2]
Explicación:
MinStack minStack = new MinStack();
minStack. push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> return -3.
minStack.pop();
minStack.top(); --> return 0.
minStack.getMin(); --> return - 2.
Nota:
las operaciones pop, top y getMin siempre se llaman en una pila no vacía.

class MinStack {
    
    
public:
    /*
    设计常数时间内检索到最小元素的栈:
    需要定义变量存储最小值,考虑到当最小值弹出后能及时更新最小值,定义了min_stack存储截止到每个位置的最小值;
    1. push(),top()操作正常;
    2. getMin()操作直接返回min_stack的栈顶元素;
    3. push()操作:
    3.1 real_stack直接入栈;
    3.2 判断x与min_stack的栈顶元素谁小,将最小值入栈;
    */

    /** initialize your data structure here. */
    MinStack() {
    
    

    }
    
    void push(int x) {
    
    
        real_stack.push(x);
        if(min_stack.empty()) min_stack.push(x);
        else min_stack.push(min(x, min_stack.top()));
    }
    
    void pop() {
    
    
        real_stack.pop();
        min_stack.pop();
    }
    
    int top() {
    
    
        return real_stack.top();
    }
    
    int getMin() {
    
    
        return min_stack.top();
    }
private:
        stack<int> real_stack;
        stack<int> min_stack;
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

394. Decodificación de cadenas

Dada una cadena codificada, devuelve su cadena decodificada.

La regla de codificación es: k[cadena_codificada], lo que significa que la cadena_codificada dentro de los corchetes se repite exactamente k veces. Tenga en cuenta que se garantiza que k es un número entero positivo.

Puede suponer que la cadena de entrada siempre es válida; no hay espacios adicionales en la cadena de entrada y los corchetes de entrada siempre tienen formato.

Además, puede pensar que los datos originales no contienen números, todos los números solo representan el número de repeticiones k, por ejemplo, no aparecerá ninguna entrada como 3a o 2[4].

Ejemplo 1:
Entrada: s = "3[a]2[bc]"
Salida: "aaabcbc"
Ejemplo 2:
Entrada: s = "3[a2[c]]"
Salida: "accaccacc"
Ejemplo 3:
Entrada: s = "2[abc]3[cd]ef"
Salida: "abcabcdcdcdef"
Ejemplo 4:
Entrada: s = "abc3[cd]xyz"
Salida: "abccdcdcdxyz"

class Solution {
    
    
public:

    /*
    将字符串s重复n遍返回;
    */
    string repeatStr(string s, int n){
    
    
        string ans = "";
        for(int i=0; i<n; i++){
    
    
            ans.append(s);
        }
        return ans;
    }

    /*
    给定一个经过编码的字符串(编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。),返回它解码后的字符串:
    1. 使用栈来进行计算,建立两个栈分别存储k和encoded_string;
    2. 定义三个状态:BEGIN,NUMBER,CHARATOR分别代表起始状态,处理数字k,处理encoded_string;
    3. 遍历s,进行处理:
    3.1 BEGIN:判断第一个字符为数字还是encoded_string;
    3.2 NUMBER:将数字入nums栈;
    3.3 CHARATOR:
    3.3.1 s[i]!=']'时,将字符直接入dec_str栈;
    3.3.2 s[i]==']'时,解码字符串:
    3.3.2.1 取出字符串栈中的元素,直到取到'['为止,取出的元素则为需要重复的元素;
    3.3.2.2 将取出的字符连成字符串并重复n遍,n为nums栈中的栈顶元素;
    3.3.2.3 将新字符串入dec_str栈;
    4. dec_str中最后存储着解码后的字符串片段,拼接之后就是最终答案;
    */
    string decodeString(string s) {
    
    
        stack<int> nums;
        stack<string> dec_str;
        static const int BEGIN = 0;
        static const int NUMBER = 1;
        static const int CHARATOR = 2;
        int flag = BEGIN;
        for(int i=0; i<s.size(); i++){
    
    
            switch(flag){
    
    
                case BEGIN:{
    
    
                    if(s[i]>='0' && s[i]<='9') flag = NUMBER;
                    else flag = CHARATOR;
                    i--;
                    break;
                }
                case NUMBER:{
    
    
                    if(s[i]<'0' || s[i]>'9') flag = CHARATOR;
                    else{
    
    
                        int temp = 0;
                        while(s[i]>='0' && s[i]<='9'){
    
    
                            temp = temp * 10 + s[i] - '0';
                            i++;
                        }
                        nums.push(temp);
                    }
                    i--;
                    break;
                }
                case CHARATOR:{
    
    
                    if(s[i]>='0' && s[i]<='9'){
    
    
                        flag = NUMBER;
                        i--;
                    } 
                    else if(s[i]!=']'){
    
    
                        string mem;
                        mem.push_back(s[i]);
                        dec_str.push(mem);
                    }
                    else{
    
    
                        /*
                        1. 取出字符串栈中的元素,直到取到'['为止,取出的元素则为需要重复的元素;
                        2. 将取出的字符连成字符串并重复n遍,n为nums栈中的栈顶元素;
                        3. 将新字符串入dec_str栈;
                        */
                        string temp_str = "";
                        while(dec_str.top()[0]!='['){
    
    
                            string top_string = dec_str.top();
                            dec_str.pop();
                            temp_str.insert(0, top_string);
                        }
                        dec_str.pop(); //去掉'['
                        int times = nums.top();
                        nums.pop();
                        string repeat_str = repeatStr(temp_str, times);
                        dec_str.push(repeat_str);
                    }
                    break;
                }
            }
        }
        string ans = "";
        while(!dec_str.empty()){
    
    
            string mem_str = dec_str.top();
            dec_str.pop();
            ans.insert(0, mem_str);
        }
        return ans;
    }
};

Supongo que te gusta

Origin blog.csdn.net/weixin_43273742/article/details/107741524
Recomendado
Clasificación