2022-6-14 栈的压入、弹出序列,括号的分数,反转每对括号间的子串,对角线遍历

1. 栈的压入、弹出序列

输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。

Example 1

输入:pushed = [1,2,3,4,5], popped = [4,5,3,2,1]
输出:true
解释:我们可以按以下顺序执行:
push(1), push(2), push(3), push(4), pop() -> 4,
push(5), pop() -> 5, pop() -> 3, pop() -> 2, pop() -> 1

Example 2

输入:pushed = [1,2,3,4,5], popped = [4,3,5,1,2]
输出:false
解释:1 不能在 2 之前弹出。

Constraints:

  • 0 <= pushed.length == popped.length <= 1000
  • 0 <= pushed[i], popped[i] < 1000 1 <= n, m <= 10^5
  • pushedpopped 的排列。

代码 [二分]

class Solution {
public:
    vector<int> successfulPairs(vector<int> &spells, vector<int> &potions, long long success) {
        sort(potions.begin(), potions.end());
        vector<int> result(spells.size());
        for (int i = 0; i < spells.size(); ++i) {
            int lo = min(100001ll, (success - 1) / spells[i] + 1);
            result[i] = potions.end() - lower_bound(potions.begin(), potions.end(), lo);
        }
        return result;
    }
};

2. 括号的分数

给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:

  • () 得 1 分。
  • ABA + B 分,其中 A 和 B 是平衡括号字符串。
  • (A)2 * A 分,其中 A 是平衡括号字符串。

Example 1

输入: "()"
输出: 1

Example 2

输入: "(())"
输出: 2

Constraints:

  • S 是平衡括号字符串,且只含有 ()
  • 2 <= S.length <= 50

代码 1 [栈 - 脑残版本]

#include<bits/stdc++.h>

using namespace std;

int main() {
    string s;
    cin >> s;
    stack<tuple<int, int, int>> scores; // start, end, score
    stack<int> st;
    for (int i = 0, prev; i < s.size(); ++i) {
        if (s[i] == '(') {
            st.push(i);
            continue;
        }
        if (!scores.empty() && st.top() == get<0>(scores.top()) - 1) { // s[i] == ')' - double
            auto[start, end, score]=scores.top();
            scores.pop();
            st.pop();
            scores.push({start - 1, end + 1, score * 2});
        } else {
            prev = st.top();
            st.pop();
            scores.push({prev, i, 1});
        }
        if (scores.size() >= 2) { // add
            auto[start, end, score]=scores.top();
            scores.pop();
            if (start == get<1>(scores.top()) + 1) {
                auto[start_, end_, score_]=scores.top();
                scores.pop();
                scores.push({start_, end, score + score_});
            } else {
                scores.push({start, end, score});
            }
        }
    }
    cout << get<2>(scores.top());

    return 0;
}

代码 2 [分治]

class Solution {
private:
    int divide(const string &s, int i, int j) {
        int ans = 0, bal = 0;
        for (int k = i; k < j; ++k) {
            bal += s[k] == '(' ? 1 : -1;
            if (bal == 0) {
                ans += k - i == 1 ? 1 : 2 * divide(s, i + 1, k);
                i = k + 1;
            }
        }
        return ans;
    }
public:
    int scoreOfParentheses(const string &s) { return divide(s, 0, s.size()); }
};

代码 3 []

class Solution {
public:
    int scoreOfParentheses(const string &s) {
        stack<int> st;
        st.push(0);
        for (char ch:s) {
            if (ch == '(') {
                st.push(0);
            } else {
                int v = st.top(); st.pop();
                int w = st.top(); st.pop();
                st.push(w + max(2 * v, 1));
            }
        }
        return st.top();
    }
};

代码 4 [统计核心的数目]

class Solution {
public:
    int scoreOfParentheses(const string &s) {
        int ans = 0, bal = 0;
        for (int i = 0; i < s.size(); ++i) {
            if (s[i] == '(') {
                bal++;
            } else {
                bal--;
                if (s[i - 1] == '(') ans += 1 << bal;
            }
        }
        return ans;
    }
};

3. 反转每对括号间的子串

给出一个字符串 s(仅含有小写英文字母和括号)。

请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。

注意,您的结果中 不应 包含任何括号。

Example 1

输入:s = "(abcd)"
输出:"dcba"

Example 2

输入:s = "(u(love)i)"
输出:"iloveu"
解释:先反转子字符串 "love" ,然后反转整个字符串。

Constraints:

  • 0 <= s.length <= 2000
  • s 中只有小写英文字母和括号
  • 题目测试用例确保所有括号都是成对出现的

代码 1 [栈]

class Solution {
public:
    string reverseParentheses(string s) {
        stack<string> st;
        string str;
        for (char ch:s) {
            if (ch == '(') {
                st.push(str);
                str = "";
            } else if (ch == ')') {
                reverse(str.begin(), str.end());
                str = st.top() + str;
                st.pop();
            } else {
                str.push_back(ch);
            }
        }
        return str;
    }
};

代码 2 [预处理括号]

class Solution {
public:
    string reverseParentheses(string s) {
        int n = s.length();
        vector<int> pair(n);
        stack<int> stk;
        for (int i = 0; i < n; i++) {
            if (s[i] == '(') {
                stk.push(i);
            } else if (s[i] == ')') {
                int j = stk.top();
                stk.pop();
                pair[i] = j, pair[j] = i;
            }
        }

        string ret;
        int index = 0, step = 1;
        while (index < n) {
            if (s[index] == '(' || s[index] == ')') {
                index = pair[index];
                step = -step;
            } else {
                ret.push_back(s[index]);
            }
            index += step;
        }
        return ret;
    }
};

4. 对角线遍历

给你一个大小为 m x n 的矩阵 mat ,请以对角线遍历的顺序,用一个数组返回这个矩阵中的所有元素。

Example 1

输入:mat = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,4,7,5,3,6,8,9]

Example 2

输入:mat = [[1,2],[3,4]]
输出:[1,2,3,4]

Constraints:

  • m == mat.length
  • n == mat[i].length
  • 1 <= m, n <= 10^4
  • 1 <= m * n <= 10^4
  • -10^5 <= mat[i][j] <= 10^5

代码

class Solution {
public:
    vector<int> findDiagonalOrder(vector<vector<int>> &mat) {
        int m = mat.size(), n = mat[0].size();
        int cnt = m + n - 1;
        vector<int> result;
        result.reserve(m * n);
        for (int k = 0, x, y, dx, dy; k < cnt; ++k) {
            if ((k & 1) == 0) { // k % 2 == 0
                x = min(k, m - 1), y = k - x;
                dx = -1, dy = +1;
            } else {
                y = min(k, n - 1), x = k - y;
                dx = +1, dy = -1;
            }
            while (x >= 0 && y >= 0 && x < m && y < n) {
                result.push_back(mat[x][y]);
                x += dx;
                y += dy;
            }
        }
        return result;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值