六月集训(第14天)—栈

1. 剑指 Offer 31. 栈的压入、弹出序列

    思路:
        模拟栈的压入过程 ,并利用一个指针指向popped序列的起始位置。当栈顶和popped序列相同时,弹栈,popped的指针向后移动一位;否则将pushed序列中的元素依次压栈。如果最后栈弹空,且指针指向了popped末尾,则满足题意。

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
       int pushed_size = pushed.size(), i = 0, j = 0;
       stack<int> S;

        while (i < pushed_size && j < pushed_size) {
            while (i < pushed_size && (S.empty() || S.top() != popped[j])) {
                S.push(pushed[i++]);
            }
            while (j < pushed_size && !S.empty() && S.top() == popped[j]) {
                S.pop();
                j++;
            }
        }

       if (S.empty() && j == pushed_size) return true;
       return false;
    }
};

2. 946. 验证栈序列

    思路:
        和第一题一样。

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        int pushed_size = pushed.size(), i = 0, j = 0;
        stack<int> S;
        while (i < pushed_size && j < pushed_size) {
            while (i < pushed_size && (S.empty() || S.top() != popped[j])) {
                S.push(pushed[i++]);
            }
            while (j < pushed_size && (!S.empty() && S.top() == popped[j])) {
                S.pop();
                j++;
            }
        }
        if (S.empty() && j == pushed_size) return true;
        else return false;
    }
};

3. 856. 括号的分数

    思路:
        好家伙,递归博大精深,刚开始的思路是将枚举左右括号的四种组合与A+B和2*A的关系,没做出来。
        再考虑成对匹配
             (1) 最外侧括号成对,则返回 2 * get_score(去掉外侧括号,剩下的字串)
             (2) 字符串中出现了前缀构成完整的括号的匹配,从完成匹配的位置 idx 作为分割,返回get_score(idx 之前的字串) + get_score(idx 之后的子串)
             递归出口:当前字串只包含()


class Solution {
    int get_scores(string s, int l, int r) {
        int cnt = 0, idx = l;
        if (l + 1== r) return 1;
        while (idx <= r) {
            cnt += (s[idx] == '(' ? 1 : (-1));
            idx++;
            if (cnt == 0) break;
        }
        
        if (idx == r + 1) return 2 * get_scores(s, l + 1, r - 1);       // 最外侧是一对括号
        else return get_scores(s, l, idx - 1) + get_scores(s, idx, r);  // 在字符串中间已经出现了完整匹配的括号,则加法计分
    }
public:
    int scoreOfParentheses(string s) {
        int s_len = s.length();
        return get_scores(s, 0, s_len - 1);
    }
};

4. 1190. 反转每对括号间的子串

    思路:
        由于括号成对出现,遍历字符串,每次将'('的位置 left 压栈,遇到')'的位置为right,此时将字符串中left ~ right部分进行翻转,并弹栈,直到遍历完整个字符串。
        上述操作再原字符串中进行,所以的到的字符串还带有括号,处理一下,即可获得不带括号的答案。

class Solution {
public:
    string reverseParentheses(string s) {
        int s_len = s.length(), i;
        stack<int> stk;
        for (i = 0; i < s_len; ++i) {
            if (s[i] == '(') stk.push(i);	/* 记录左括号位置 */
            else if (s[i] == ')') {			/* 翻转区间left ~ right 的字符串 */
                int l = stk.top(), r = i;
                while (l < r) {
                    swap(s[l++], s[r--]);
                }
                stk.pop();
            }
        }
        string ans;
        // 获取不带括号的答案字符串
        for (i = 0; i < s_len; ++i) if (s[i] != '(' && s[i] != ')') ans += s[i];
        return ans;
    }
};
posted @ 2022-06-14 09:16  番茄元  阅读(28)  评论(0)    收藏  举报