开宗明义:本系列基于小象学院林沐老师课程《面试算法 LeetCode 刷题班》,刷题小白,旨在理解和交流,重在记录,望各位大牛指点!
Leetcode学习之栈、队列、堆(2)
1、包含min函数的栈 Leetcode 155.
题目来源:
L
e
e
t
c
o
d
e
155.
M
i
n
S
t
a
c
k
Leetcode \ 155. \ Min \ Stack
Leetcode 155. Min Stack
题目描述:设计一个栈,支持
p
u
s
h
(
x
)
、
p
o
p
(
)
、
t
o
p
(
)
、
g
e
t
M
i
n
push(x)、pop()、top()、getMin
push(x)、pop()、top()、getMin操作,其中
g
e
t
M
i
n
(
)
getMin()
getMin()返回栈内最小元素。
要求描述:
思路:首先考虑一个变量能否记录上述所有状态的最小值。
因此,使用另一个栈,存储各个状态最小值。
测试代码:
#include <stdio.h>
#include <stack>
using namespace std;
class MinStack {
public:
MinStack(){}
void push(int x) {
_data.push(x); //将数据压入数据栈
if (_min.empty()) {
_min.push(x);
} //如果最小值栈空,直接将数据压入栈
else
{//比较当前数据与最小值栈顶数据大小,选择较小的压入最小值栈
if (x > _min.top()) {
x = _min.top();
}
_min.push(x);
}
}
void pop() {
_data.pop();
_min.pop();//数据栈与最小值栈同时弹出
}
int top() {
return _data.top();
}
int getMin() {
return _min.top();
}
private:
stack<int> _data;//数据栈
stack<int> _min;//最小值栈
};
2、合法的出栈序列
题目来源:
p
o
j
1363
R
a
i
l
s
poj \ 1363 \ Rails
poj 1363 Rails
题目描述:已知从1至n的数字序列,按顺序入栈,每个数字入栈后即可出栈,也可在栈中停留,等待后面的数字 入栈 出栈 后,该数字再出栈,求数字序列的出栈序列是否合法?
要求描述:
思路:使用栈与队列模拟入栈、出栈过程
测试代码:
#include <stack>
#include <queue>
#include <iostream>
using namespace std;
bool check_is_valid_order(queue<int> &order) { //检查序列(存储在队列中)
stack<int> s;//s为模拟栈
int n = order.size();//n为序列长度,将1-n入栈
for (int i = 1; i <= n; i++) {
s.push(i);//将i入栈
while (!s.empty()&&order.front()==s.top())
{
s.pop();//只要s不空且队列头部与栈顶相同,即弹出元素
order.pop();
}
}
if (!s.empty()) {
return false;
}
return true;
}
3、简单的计算器 Leetcode 224.
题目来源:
L
e
e
t
c
o
d
e
224.
B
a
s
i
c
C
a
l
c
u
l
a
t
o
r
Leetcode \ 224. \ Basic \ Calculator
Leetcode 224. Basic Calculator
题目描述:设计一个计算器,输入一个字符串存储的数学表达式,可以包括"("、“)”、“+”、“-”四种符合的数学表达式,输入的数学表达式字符串保证合法的,输入的数学表达式中可能存在空格字符。
要求描述:
思路:栈内元素计算,栈可以用来去括号,处理优先级问题。遇见 ‘(’ 不能计算,直到遇到 ‘)’ 才继续计算。
字符串处理(状态机的思想)
测试代码:
#include <string>
#include <stack>
using namespace std;
class Solution {
public:
int Calculate(std::string s) {
static const int state_begin = 0;//开始状态,状态用常量表示
static const int number_state = 1;//数字状态
static const int operation_state = 2;//操作符状态
stack<int> number_stack;//数字栈
stack<char> operation_stack;//操作符栈
int number = 0;
int state = state_begin;
int compuate_flag = 0;//记录要不要计算,初始化
for (int i = 0; i < s.length(); i++) {
if (s[i] == ' ') {
continue;
}
switch (state)//状态切换
{
case state_begin:
if (s[i] >= '0'&&s[i] <= '9') {
state = number_state; //数字状态
}
else{
state = operation_state;//操作符状态
}
i--;
break;
case number_state:
if (s[i] >= '0'&&s[i] <= '9') {
number = number * 10 + s[i] - '0';
}
else
{
number_stack.push(number); //数字栈
if (compuate_flag == 1) { //开始计算
compute(number_stack, operation_stack);
}
number = 0;
i--;
state = operation_state;
}
break;
case operation_state:
if (s[i] == '+' || s[i] == '-') {
operation_stack.push(s[i]);
compuate_flag = 1;
}
else if (s[i] == '(') {
state = number_state;
compuate_flag = 0;//左括号不能计算
}
else if (s[i] >= '0'&&s[i] <= '9') {
state = number_state;
i--;
}
else if (s[i] == ')') { //右括号计算
compute(number_stack, operation_stack);
}
break;
}
}
if (number != 0) {
number_stack.push(number);
compute(number_stack, operation_stack);
}
if (number == 0 && number_stack.empty()) {
return 0;
}
return number_stack.top();
}
void compute(stack<int> &number_stack, stack<char> &operation_stack) {//传引用,防止数据过大,拷贝出问题
if (number_stack.size() < 2) {
return;
}
int num2 = number_stack.top();
number_stack.pop();
int num1 = number_stack.top();
number_stack.pop();
if (operation_stack.top() == '+') {
number_stack.push(num1 + num2);
}
else if (operation_stack.top() == '-'){
number_stack.push(num1 - num2);
}
operation_stack.pop();
}
};
int main() {
string s = "1+121-(14+(5-6))";
Solution solve;
printf("%d\n", solve.Calculate(s));
system("pause");
return 0;
}
字符串转换成数字:
number = number * 10 + s[i]-'0'//number*10表示从高位开始,往下乘10