【六月集训】day14 栈

本文详细介绍了C++中vector的扩容策略,即0.5倍倍增capacity并修正。同时,阐述了栈的基本概念,包括栈顶、栈底、入栈和出栈操作,并提供了顺序表和链表两种实现方式。接着,通过三个具体的编程题目——栈的压入、弹出序列,验证栈序列,以及括号的分数,展示了栈在实际问题中的应用。文章以代码示例辅助理解,加深读者对栈操作的理解。
摘要由CSDN通过智能技术生成

写在前面

对待刷题就跟对待喜欢的人一样,一天都不能断。

今日内容

vector扩容策略:

扩容的策略是 0.5倍倍增 capacity,然后做一个简单修正。

英文原文:C++ Made Easier: How Vectors Grow | Dr Dobb'sThe Standard C++ library delivers reasonable performance by default. If you've ever wondered how, or what is implied in the word "reasonable, read onhttps://www.drdobbs.com/c-made-easier-how-vectors-grow/184401375

中文翻译:《C/C++ 面试 100 例》(四)vector 扩容策略_英雄哪里出来的博客-CSDN博客面试官:简单谈一下 vector 的扩容策略?https://blog.csdn.net/WhereIsHeroFrom/article/details/108750216

栈是仅限在表尾进行插入和删除的线性表。先进后出,后进先出,即最先进入栈的元素最后出栈。

  • 栈顶与栈底

栈顶带有栈顶指针,栈底是第一个元素存放的地方。一般只关心栈顶。

  • 出栈与入栈

入栈:元素进入栈,栈顶指针加一,栈长加一。

出栈:元素pop出栈,栈顶指针减一,栈长减一。当然这得在栈里有元素的时候。

清空栈:一直出栈,知道栈内无元素。

  • 栈的实现

可分为顺序表实现和链表实现。

顺序表实现:

```

#define DataType int        // (1)
#define maxn 100005         // (2)

struct Stack {              // (3)
    DataType data[maxn];    // (4)
    int top;                // (5)
};

```

链表实现

```

typedef int DataType;             // (1)
struct StackNode;                 // (2)
struct StackNode {                // (3)
    DataType data;
    struct StackNode *next;
};
struct Stack {                    
    struct StackNode *top;        // (4)
    int size;                     // (5)
};

```

概念千百遍,不如题目来一遍。

题目

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

解题思路:

1、设置两个指针,i指向pushed数组当前的元素,j指向popped数组当前的元素

2、每次循环,将pushed数组当前元素入栈

3、判断popped当前元素是否与栈顶元素相同,相同则出栈,并将当前元素向后移动一位

4、如果pushed数组已经全部入栈,并且popped数组中仍有元素,则不合法,返回false,否则返回true;

class Solution {
public:
    bool validateStackSequences(vector<int>& pushed, vector<int>& popped) {
        int i = 0, j = 0;
        stack<int> stk;
        if (pushed.size() != popped.size()) return false; //长度不一致直接返回false
        while (i < pushed.size() && j < popped.size()) { 
            stk.push(pushed[i++]); //pushed元素入栈
            while (!stk.empty() && stk.top() == popped[j]) { //栈值与poped值比对
                stk.pop();
                j++;
            }
            if (i == pushed.size() && j < popped.size()) return false; //pushed元素已全部入栈,比对过后,j还有元素存在,返回false
        }

        return true;

    }
};

946. 验证栈序列

解题思路:同上题一致

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


    }
};

856. 括号的分数

解题思路:

1、定义一个递归函数,计算某段合格的平衡字符串区间的分数;

2、如果这段区间为2,则分数就是1;否则从左到右便利,遇到‘(’则计数器加1,否则计数器-1,当计数器为0时跳出循环;

3、这个时候要么得到的串是可以分割成两个单独的串,要么就是(A)这种情况,分别计算分数即可。

class Solution {
    int scoreOfParentheses(const string& s, int l, int r) {
        if (l + 1 == r) return 1; //一对括号
        int cnt = 0;
        int start = l;
        while (1) {
            cnt += (s[start] == '(' ? 1 : -1); //找到完整的() 
            ++start;
            if (cnt == 0) break;
        }
        if (start == r+1) return 2 * scoreOfParentheses(s, l+1, r-1); //只有一个平衡括号字符串
        return scoreOfParentheses(s, l, start -1) + scoreOfParentheses(s,start, r); //左右两边都是平衡括号字符串,可以分别计算
    }
public:
    int scoreOfParentheses(string s) {
        return scoreOfParentheses(s, 0, s.size()-1);
    }
};

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

解题思路:

1、定义一个函数,专门计算字符串从某个start位置开始得到的反转后的字符串

2、遍历左右字符串,遇到左括号(递归翻转括号内的字符串),右括号(返回当前字符串),和字符分别处理(字符串直接加上);

3、递归返回的过程,进行一次翻转,表示此次递归的情况下必定是一个括号内的串

class Solution {
    int index;
    string dfs(const string& s, int start) {
        string ret;
        for (index = start; index < s.size(); ++index) {
            if (s[index] == '(') {
                string st = dfs(s, index+1);
                reverse(st.begin(), st.end());
                ret += st;
            } else if (s[index] == ')') {
                return ret;
            } else {
                ret += s[index];
            }
        }
        return ret;
    }
public:
    string reverseParentheses(string s) {
        return dfs(s, 0);
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值