C ++アルゴリズム学習(スタック)

スタックとは何ですか?

これは、操作が制限された線形テーブルであり、テーブルの最後、つまり後入れ先出しでのみ挿入および削除できます。(初心者はアルゴリズム図を検索することを提案します、説明は非常に明確です)

質問の種類

原理学習:
155、71、682、341単調スタック:42,496、1081
補助スタック(数えるための単なるツール):1021、331
個人的には新しいタイプはないと感じており、基本的に質問の記録を繰り返さないでください。

シーケンシャルスタック

理解していただければ、百度百科は大丈夫です。誤解を招く恐れがあるのでメモも取ります。リンク
シーケンススタックの適用(要約するにはアルゴリズムが多すぎます):
明らかなソート現象があるか、左側または右側で最初の最大(最小)の状況が見つかります。

練習トピック

155.最小限のスタック

struct Node{
    
    
        int val;
        int min;
        Node *next;
};
//建立结构体,写入题目要求的功能
class MinStack {
    
    
private:
Node* head;
public:
    MinStack() {
    
     
    head = nullptr;
    }
    //构造函数
    void push(int x) {
    
    
    if(head != NULL){
    
    
    int temp = (head -> min > x)? x : head -> min;
    Node *node = new Node();
    node -> min = temp;
    node -> val = x;
    node -> next = head;
    head = node;
    }//这里使用头插
    else{
    
    
        head = new Node();
        head -> val = x;
        head -> min = x;
        head -> next = nullptr;
    }
    }
    void pop() {
    
    
        head = head ->next;
    }
    
    int top() {
    
    
    return head -> val;
    }
    int getMin() {
    
    
    return head -> min;
    }
};

42.雨を降らせる

これは、単調に減少するスタックを使用します。
単調に減少するスタックと単調に増加するスタックについて少し説明します。
(例として単調に減少するスタックを取り上げます)
1。データがスタックの最上位要素よりも小さい場合、データはにプッシュされます。スタック。
2.データがスタックの最上位要素よりも大きい場合、データがスタックの最上位要素よりも小さくなるまで、スタックの最上位要素がスタックからポップされます。

例:4312
4,3,1は通常スタック
に2にプッシュされ、1が比較され、1がポップされ、3が比較され、結果は3未満になります。

この質問では、水滴がある場所の領域を尋ねるだけでよいので、スタックに保存されているデータは配列の添え字です(もちろん他の解決策もありますが、私はスタックを使用しますここに)

class Solution {
    
    
public:
    int trap(vector<int>& height) {
    
    
    stack<int> num;
    int sum = 0;
    for(int i = 0;i < height.size();i++){
    
    
        while(!num.empty() && height[num.top()] < height[i]){
    
    
            int val = height[num.top()];
            num.pop();
            if(num.empty()) break;
            int l = i - num.top() - 1;
            int h = min(height[i],height[num.top()]) - val;
            sum += l * h;
        }
        num.push(i);
    }
    return sum;
    }
};

71.パスを簡素化する

質問と例を読んだ後、私が得た情報は次のとおり
です。1。スタックの最上位が/次にプッシュされるデータも/その場合、スタックの最上位がポップアウトされ、次のデータは通常、にプッシュされます。スタック。
2.スタックの最上位が/の場合(この場合、ランダムに入力する場合を除外しません)、スタックにプッシュされる次のデータは...次に、すべてのデータがスタックからポップされ、次のデータはスタックにプッシュされます。
3.スタックの最上位が/の場合、次にプッシュされるデータはです。次に、スタックの最上位がポップされ、次のスタックの最上位にポップし続けます/
4。プログラムの実行の最後に、スタックの一番上が/であるかどうか、スタックからポップアウトであるかどうかを判断します。
言い方をすれば、2つのものの間にあるものを判断し、対応する操作を行う必要があります。

class Solution {
    
    
public:
    string simplifyPath(string path) {
    
    
    path += '/';
    stack<string> stk;
    string str;
    for(char m : path){
    
    
        if(m == '/'){
    
    
            //如果str为.那么直接清除str即可
            //如果str为..那么stk把上一个数据给出栈(这里有特殊情况/../需要判断是否为空栈)
            //其他情况就把数据读进去,注意我这么写'/'这个字符是不会读进去的
            if(str == ".." && !stk.empty()){
    
    
                stk.pop();
            }
            else if(str != "." && !str.empty() && str != ".."){
    
    
                stk.push(str);
            }
            str.clear();
        }
        else{
    
    
            str.push_back(m);
        }
    }
    string result;
    if(stk.empty()) return "/";
    while(!stk.empty()){
    
    
        result = "/" + stk.top() + result;
        stk.pop();
    }
    return result;
    }
};

496.次の大要素I

この質問では、番号の降順を使用し、小さなデータを保存して右側の最初のビッグデータを見つけ、関係を保存し(スタックの一番上をポップすることを忘れないでください)、ハッシュマップを使用して関係を確立し、最後に戻り値-1が見つからない場合は、結果を確認してください。

class Solution {
    
    
public:
    vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
    
    
    stack<int> num;
    vector<int> answer;
    map<int, int> s1;
    for(auto a:nums2){
    
    
        while(!num.empty() && num.top() < a){
    
    
            s1[num.top()] = a;
            num.pop();
        }
        num.push(a);
    }
    for(auto a:nums1){
    
    
        if(s1.count(a) == 0) answer.push_back(-1);
        else answer.push_back(s1[a]);
    }
    return answer;
    }
};

682.野球の試合

この質問も手話の質問です。aslコードを使用すると思いましたが、野球の試合で60ポイントを獲得する方法がわかりません。

class Solution {
    
    
public:
    int calPoints(vector<string>& ops) {
    
    
    stack<int> num;
    int sum = 0;
    for(auto a:ops){
    
    
        if(a[0] == '+'){
    
    
            int t = num.top();
            num.pop();
            int t1 = t + num.top();
            num.push(t);
            num.push(t1);
        }
        else if(a[0] == 'D'){
    
    
            int t = num.top() + num.top();
            num.push(t);
        }
        else if(a[0] == 'C'){
    
    
            num.pop();
        }
        else num.push(stoi(a));//大家可以记一下这个函数
    }
    while(!num.empty()){
    
    
        sum += num.top();
        num.pop();
    }
    return sum;
    }
};

1021.最も外側の括弧を削除します

私は2つのスタック間の距離を探し、2つのスタック間の距離を合計することから始めましたが、大物が書いたものを読みました==恥ずかしいことであり、参照ユーザー:ping-ze-ping -ze-ping-ping -zeコード。

class Solution {
    
    
public:
    string removeOuterParentheses(string S) {
    
    
        stack<char> a;
        string b("");
        for(int i = 0;i < S.length();i++){
    
    
            if(S[i] == ')') a.pop();
            if(!a.empty() ) b += S[i];
          if(S[i] == '(')  a.push(S[i]);
        }
        return b;
    }
}

341.ネストされたリストイテレータのフラット化

中難易度の質問は、ハンドトレーニングに適しています(最初は質問の意味がわからなかったので、書くのが面倒でした)。

class NestedIterator {
    
    
private:
stack<int> a;
stack<int> b;
void add(vector<NestedInteger> nested){
    
    
    for(auto nestedi : nested)
        if(nestedi.isInteger()) a.push(nestedi.getInteger());
        else add(nestedi.getList());
}
public:
    NestedIterator(vector<NestedInteger> &nestedList) {
    
    
        add(nestedList);
        while(!a.empty()){
    
    
            b.push(a.top());
            a.pop();
        }
    }
    int next() {
    
    
        int ai = b.top();
        b.pop();
        return ai;
    }
    bool hasNext() {
    
    
        return !b.empty();
    }
};

331.バイナリツリーの事前注文のシリアル化を確認します

これは二分木です==とにかく、私の印象は次のとおりです。空のノードの数=空でないノードの数+1。ツリーに関するいくつかの定理を覚えておくことをお勧めします。
次に、#が空で、数値が空ではなく、#が数値より1大きい場合、それが数値の場合はスタックにプッシュされ、#の場合はスタックからポップされます。文字が#で、#が文字列の最後の桁で、スタックが空かどうかを確認する場合空の場合は検証が成功したことを意味し、空でない場合は検証が失敗したことを意味します。
それから書き留めたところ、2桁の数字19に出会ったのですが、これは文字列なので、やりにくいです==他の人の慣習から借りて、数字を見つけるたびに、次の数字を探すために降りてきます"、"たくさんあります "、" 1つしかない、このアイデアは本当に強力だと言わざるを得ません。

class Solution {
    
    
private:
stack<char> a;
public:
    bool isValidSerialization(string preorder) {
    
    
    if (preorder.empty()) return false;
    for(int i = 0;i < preorder.length();i++){
    
    
        if(preorder[i] == '#'){
    
    
            if(a.empty()) return i == preorder.size() - 1;
            else {
    
    
                a.pop();
                i++;
            }
        }
        else{
    
    
            while (i < preorder.size() && preorder[i] != ',') i++;
            a.push(preorder[i]);
        }
    }
    return false;
    }
};

1081.異なる文字の最小のサブシーケンス

この問題の原理は非常に単純です。単調なスタックです(単調に増加します)。データがすでにスタックに存在する場合は、このデータを渡します。データがスタックの最上位よりも小さい場合は、最上位のデータを削除します。スタックの最上位のデータがデータより少なくなるまで、スタックの C ++にはライブラリ関数がほとんどないため、代わりにベクトルを使用します。実際、goとpythonを使用してライブラリを直接調整できます。

class Solution {
    
    
public:
    bool get_num(int i,string s,char si){
    
    
        for(int j = i + 1;j<s.length();j++) if(s[j] == si) return true;
        return false;
    }
    string smallestSubsequence(string s) {
    
    
     string str("");
     vector<char> already;
     int i = -1;
     for(auto si :s){
    
    
         i++;
         if(count(already.begin(),already.end(),si) > 0) continue;
         while(!already.empty() && already.back() > si && get_num(i,s,already.back()) == true) already.pop_back();
         already.push_back(si);
     }
     while(!already.empty()){
    
    
         str = already.back() + str;
         already.pop_back();
     }
     return str;
    }
};

おすすめ

転載: blog.csdn.net/weixin_45743162/article/details/113619752