Leetcode-Pinselnotizen (C++) – Stapelwarteschlange

Leetcode-Pinselnotizen (C++) – Stapelwarteschlange

Sortieren Sie die Ideen beim Bearbeiten der Fragen, fassen Sie sie zusammen und teilen Sie sie hier.
Github-Adresse: https://github.com/lvjian0706/Leetcode-solutions
Das Github-Projekt wird neu erstellt und der Code und die Ideen werden nacheinander hochgeladen. Der Code basiert auf C++ und Python. Gleichzeitig wird auch der grundlegende Sortieralgorithmus sortiert und hochgeladen.

94. Inorder-Traversierung eines Binärbaums

Geben Sie bei einem gegebenen Binärbaum dessen Inorder-Traversal zurück.

Beispiel:

Eingabe: [1,null,2,3]
1

2
/
3

Ausgabe: [1,3,2]
Fortgeschritten: Der rekursive Algorithmus ist sehr einfach. Kann man das mit einem iterativen Algorithmus machen?

/**
 * 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. Umgekehrte polnische Ausdrucksbewertung

Wertet den Ausdruck in umgekehrter polnischer Notation aus.

Zu den gültigen Operatoren gehören +, -, *, /. Jeder Operand kann eine Ganzzahl oder ein anderer umgekehrter polnischer Ausdruck sein.

veranschaulichen:

Bei der Ganzzahldivision bleibt nur der ganzzahlige Teil erhalten.
Der angegebene umgekehrte polnische Ausdruck ist immer gültig. Mit anderen Worten: Der Ausdruck ergibt immer einen gültigen Wert und es erfolgt keine Division durch Null.

Beispiel 1:
Eingabe: ["2", "1", "+", "3", " " ]
Ausgabe: 9
Erläuterung: Diese Formel wird in einen allgemeinen arithmetischen Infix-Ausdruck umgewandelt: ((2 + 1) * 3) = 9
Beispiel 2:
Eingabe: ["4", "13", "5", "/", "+"]
Ausgabe: 6
Erläuterung: Diese Formel wird in einen gemeinsamen Infix-Arithmetikausdruck umgewandelt: (4 + (13 / 5)) = 6
Beispiel 3:
Eingabe: ["10", "6", "9", "3", "+", "-11", " ", "/", "* " , "17
" , „+“, „5“, „+“]
Ausgabe: 22
Erläuterung:
Diese Formel wird in einen allgemeinen arithmetischen Infix-Ausdruck umgewandelt:
((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

Umgekehrter polnischer Ausdruck:
Der umgekehrte polnische Ausdruck ist ein Suffixausdruck, das sogenannte Suffix bedeutet, dass der Operator dahinter geschrieben wird.
Die häufig verwendete Formel ist ein Infix-Ausdruck wie ( 1 + 2 ) * ( 3 + 4 ).
Der umgekehrte polnische Ausdruck dieser Formel ist ( ( 1 2 + ) ( 3 4 + ) * ).
Der umgekehrte polnische Ausdruck hat die folgenden zwei Vorteile:
Der Ausdruck weist nach dem Entfernen der Klammern keine Mehrdeutigkeit auf. Selbst wenn die obige Formel als 1 2 + 3 4 + * geschrieben wird, kann das korrekte Ergebnis entsprechend der Reihenfolge berechnet werden.
Es eignet sich für Stapeloperationen: Wenn eine Zahl angetroffen wird, wird sie auf den Stapel verschoben. Wenn ein Operator angetroffen wird, werden die beiden Zahlen oben auf dem Stapel zur Berechnung herausgenommen und das Ergebnis auf den Stapel verschoben.

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. Minimaler Stapel

Entwerfen Sie einen Stapel, der Push-, Pop- und Top-Operationen unterstützt und das kleinste Element in konstanter Zeit abrufen kann.

push(x) – schiebt Element x auf den Stapel.
pop() – entfernt das Element oben im Stapel.
top() – Holen Sie sich das oberste Element des Stapels.
getMin() – ruft das kleinste Element im Stapel ab.

Beispiel:
Eingabe:
["MinStack", "push", "push", "push", "getMin", "pop", "top", "getMin"] [[],[-2],[0]
, [-3],[],[],[],[]]
Ausgabe:
[null,null,null,null,-3,null,0,-2]
Erläuterung:
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.
Hinweis:
Pop-, Top- und getMin-Operationen werden immer auf einem nicht leeren Stapel aufgerufen.

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. String-Dekodierung

Geben Sie bei gegebener codierter Zeichenfolge die decodierte Zeichenfolge zurück.

Die Codierungsregel lautet: k[encoded_string], was bedeutet, dass der encoded_string in den eckigen Klammern genau k-mal wiederholt wird. Beachten Sie, dass k garantiert eine positive ganze Zahl ist.

Sie können davon ausgehen, dass die Eingabezeichenfolge immer gültig ist; die Eingabezeichenfolge enthält keine zusätzlichen Leerzeichen und die eckigen Eingabeklammern sind immer formatiert.

Sie können sich auch vorstellen, dass die Originaldaten keine Zahlen enthalten, alle Zahlen stellen nur die Anzahl der Wiederholungen k dar, z. B. werden keine Eingaben wie 3a oder 2[4] angezeigt.

Beispiel 1:
Eingabe: s = „3[a]2[bc]“
Ausgabe: „aaabcbc“
Beispiel 2:
Eingabe: s = „3[a2[c]]“
Ausgabe: „accaccacc“
Beispiel 3:
Eingabe: s = „2[abc]3[cd]ef“
Ausgabe: „abcabccdcdcdef“
Beispiel 4:
Eingabe: s = „abc3[cd]xyz“
Ausgabe: „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;
    }
};

おすすめ

転載: blog.csdn.net/weixin_43273742/article/details/107741524