[英雄星球六月集训LeetCode解题日报] 第14日 栈
一、 剑指 Offer 31. 栈的压入、弹出序列
1. 题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如,序列 {1,2,3,4,5} 是某栈的压栈序列,序列 {4,5,3,2,1} 是该压栈序列对应的一个弹出序列,但 {4,3,5,1,2} 就不可能是该压栈序列的弹出序列。
2. 思路分析
- 用栈模拟入队,遇到出队数字时尝试出队。
- 如果最后能出完就是正确。
3. 代码实现
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
stack = []
i = 0
for p in pushed:
stack.append(p)
while stack and stack[-1] == popped[i]:
stack.pop()
i += 1
return not stack
二、 946. 验证栈序列
链接: 946. 验证栈序列
1. 题目描述
给定 pushed 和 popped 两个序列,每个序列中的 值都不重复,只有当它们可能是在最初空栈上进行的推入 push 和弹出 pop 操作序列的结果时,返回 true;否则,返回 false 。
2. 思路分析
同上题。
3. 代码实现
class Solution:
def validateStackSequences(self, pushed: List[int], popped: List[int]) -> bool:
stack = []
i = 0
for p in pushed:
stack.append(p)
while stack and stack[-1] == popped[i]:
stack.pop()
i += 1
return not stack
三、 856. 括号的分数
链接: 856. 括号的分数
1. 题目描述
给定一个平衡括号字符串 S,按下述规则计算该字符串的分数:
- () 得 1 分。
- AB 得 A + B 分,其中 A 和 B 是平衡括号字符串。
- (A) 得 2 * A 分,其中 A 是平衡括号字符串。
2. 思路分析
好像之前群友出过一道类似的题,用括号处理内部字符串重复次数。
这种题可以用栈维护每个“级别”的子问题,当前级别括回时,转移回上一级别,并出栈。
这题:
- 遇到’(',栈升高,为空(0)等待。
- 遇到’)',当前栈顶关闭,加回上一层,注意转移关系是要乘2 (条件3) 再加;关闭时判断自己是否空(0),来进行+1 (条件1) 或者*2 (条件2) 操作。
- 为了
回到上一层
这个动作方便处理,我们一开始就设置一个栈底,最后结果返回栈底即可。
3. 代码实现
class Solution:
def scoreOfParentheses(self, s: str) -> int:
stack = [0]
for c in s:
if c == '(':
stack.append(0)
else:
if stack[-1] == 0:
stack[-1] = 1
else:
stack[-1] *= 2
stack[-2] += stack[-1]
stack.pop()
return stack[0]
四、 1190. 反转每对括号间的子串
链接: 1190. 反转每对括号间的子串
1. 题目描述
给出一个字符串 s(仅含有小写英文字母和括号)。
请你按照从括号内到外的顺序,逐层反转每对匹配括号中的字符串,并返回最终的结果。
注意,您的结果中 不应 包含任何括号。
2. 思路分析
与上题类似,但是每层维护的是本层字符串,且关闭
操作是翻转,因此最坏复杂度可能到O(n2)。
- 遇到’(‘,栈升高,为空(’')等待。
- 遇到’)',当前栈顶关闭,追加回上一层,这里关闭操作是翻转。
- 遇到字母直接追加到栈顶字符串。
- 为了
回到上一层
这个动作方便处理,我们一开始就设置一个栈底,最后结果返回栈底即可。
3. 代码实现
class Solution:
def reverseParentheses(self, s: str) -> str:
stack = ['']
for c in s:
if c == '(':
stack.append('')
elif c != ')':
stack[-1] += c
else:
tmp = stack.pop()
stack[-1] += tmp[::-1]
return stack[0]
五、 群友作业
1. 题目描述
2. 思路分析
类似,但是每层维护当前层字符串,大致逻辑:遇到’)‘时关闭当前层,去后边找到第一个数字,重复后加回上一层;
由于’)‘后必跟因此实际上是遇到’>'再关闭
- 遇到’(‘,栈升高,为空(’')等待。
- 遇到’)',当前栈顶关闭,追加回上一层,这里关闭操作是重复n次。
- 遇到字母直接追加到栈顶字符串。
- 为了
回到上一层
这个动作方便处理,我们一开始就设置一个栈底,最后结果返回栈底即可。
3. 代码实现
python
import collections
import heapq
import math
from bisect import bisect, bisect_left
from collections import Counter, deque
from functools import cache
from typing import List, Optional
class Solution:
def calc(self, s) -> str:
stack = ['']
num = ''
for c in s:
if c == '(':
stack.append('')
elif c.isalpha():
stack[-1] += c
elif c == ')':
pass
elif c.isdigit():
num += c
elif c == '<':
num = ''
elif c == '>':
v = stack.pop()*int(num)
stack[-1] += v
return stack[0]
if __name__ == '__main__':
ss = ["abc(d)<2>e", "a(b(c)<3>d)<2>e", "a(b(c)<3>d)<2>e"]
for s in ss:
print(Solution().calc(s))
当初写的是cpp
,硬是麻烦。
/*
* File: hdu.cpp
* Author: LIU
*/
#include <cstring>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <map>
#include <set>
#include <functional>
#include <queue>
#include <vector>
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
#ifdef DEBUG
freopen("ojin.txt", "r", stdin);
// freopen("ojout.txt", "w", stdout);
#endif
char no_use[10005]="";
char record[] = "a(b(c)<3>d)<2>e";
int len = strlen(record);
char stack[200][10005];
int top = 0;
memset(stack,0,sizeof(stack));
for (int i = 0;i < len;++i)
{
char c = record[i];
char* stack_top = stack[top];
int len_top = strlen(stack_top);
if ('a'<=c&&c<='z')
{
stack_top[len_top] = c; // c写追加好恶心,yue
}
if (c == '(')
{
++top;
}
if (c == ')')
{
int repeat = 0;
sscanf(record+i,")<%d%s",&repeat,no_use);
i = strstr(record+i,">")-record;
while(--repeat > 0)
{
memcpy(stack_top+strlen(stack_top), stack_top, len_top);
}
strcpy(stack[--top]+strlen(stack[top]),stack_top);
}
}
printf("%s\n",stack[0]);
// for(int i = 0; i <= top; ++i)
// {
// printf("%s\n",stack[i]);
// }
return 0;
}
六、参考链接
- 链接: 《画解数据结构》九个动图,画解栈