算法模板-----栈和队列
Posted 栋次大次
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法模板-----栈和队列相关的知识,希望对你有一定的参考价值。
目录
min-stack
evaluate-reverse-polish-notation
decode-string
binary-tree-inorder-traversal
clone-graph
number-of-islands
largest-rectangle-in-histogram
implement-queue-using-stacks
01-matrix
栈
特点是先入后出,利用这个特点可以保存一些临时数据,之后用到再以此弹出,常用于DFS深度搜索。
队列是先用先出,常用于BFS广度搜索,类似层次遍历。
下面根据一些例题来学习下栈的用法。
设计一个支持push、pop、top操作,并且能在常数时间内检索到最小元素的栈。
用两个栈实现,一个栈始终保证最小值在顶部。
class MinStack
private:
stack<int> normalStack;
stack<int> min_stack;
public:
MinStack()
min_stack.push(INT_MAX);
void push(int x)
normalStack.push(x);
min_stack.push(min_stack.top(), x);
void pop()
normalStack.pop();
min_stack.pop();
int top()
return normalStack.top();
int getMin()
return min_stack.top();
;
evaluate-reverse-polish-notation
根据逆波兰表达式求解,逆波兰表达式 > 输入[“2”, “1”, “+”, “3”, “*”] > 输出:9 ,((2+1)*3) = 9
通过栈保存原来的元素,遇到表达式弹出运算,再压入结果,重复这个过程。
int evalRPN(vector<string>& token)
if(tokens.size() == 0) return 0;
stack<int> res;
for(string s : tokens)
if(s != "+" && s != "-" && s != "*" && s != "/")
res.push(stoi(s));
else
int b = res.top();
res.pop();
int a = res.top();
res.pop();
if(s == '+') res.push(a + b);
if(s == '-') res.push(a - b);
if(s == '*') res.push(a * b);
if(s == '/') res.push(a / b);
return res.top();
给定一个经过编码的字符串,返回它解码后的字符串
s = ‘3[a]2[bc]’ ’ -> ‘aaabcbc’
通过栈进行操作
string decodeString(string s)
string res;
int num = 0;
stack<int> stackInt;
stack<string> stackStr;
for(char c : s)
if(c == '[')
stackInt.push(num);
num = 0;
stackStr.push(res);
res = "";
else if(c == ']')
int times = stackInt.top(); // 重复次数
stackInt.pop();
for(int i = 0; i < times; i++)
stackStr.top() += res;
res = stackStr.top();
stackStr.pop();
else if(c >= '0' && c <= '9')
num = num * 10 + c - '0';
else
res = res + c;
栈进行DFS递归搜索
栈进行递归搜索的模板
boolean DFS(int root, int target)
Set<Node> visited;
Stack<Node> s;
add root to s;
while(s is not empty)
Node cur = the top element in s;
return true if cur is target;
for(Node next : the neighbors of cur)
if(next is not in visited)
add next to s;
add next to visited;
remove cur from s;
return false;
二叉树中序遍历
使用栈保存已经访问过的节点,用于原路返回
vector<int> inorderTraversal(TreeNode* root)
vector<int> res;
if(root == NULL) return res;
stack<TreeNode*> s;
s.push(root);
while(!s.empty())
TreeNode *top = s.top();
s.pop();
if(top != NULL)
// 中序遍历 左根右
if(top->right) s.push(top->right);
s.push(top);
s.push(NULL); // 插入空节点标记访问过
if(top->left) s.push(top->left);
else
res.push_back(s.top()->val);
s.pop();
return res;
给一个无向连通图一个节点的引用,返回改图的深拷贝
unordered_map<Node*, Node*> mp; // 标记访问过的节点
Node* cloneGraph(Node* node)
if(node == NULL) return node;
if(mp.count(node)) return mp[node]; //结束递归
const auto newNode = new Node(node->val);
mp[node] = newNode;
for(auto n : node->neighbors)
mp[node]->neighbors.push_back(cloneGraph(n));
return mp[node];
给定一个由’1’陆地和’0’水组成的二维网络,计算岛屿的数量。一个岛屿被水包围,并且它是通过水平或者垂直方向上与陆地连接而成,你可以假设网络的四个边均被水包围。
通过深度搜索遍历所有的可能性(标记已经访问过的节点)
这是经典的题目,面试中很常见
int numIslands(vector<vector<char>>& grid)
int count = 0;
for(int i = 0; i < grid.size(); i++)
for(int j = 0; j < grid[0].size(); j++)
if(grid[i][j] == '1')
dfs(grid, i, j);
count++;
return count;
void dfs(vector<vector<char>>& grid, int i, int j)
if(i < 0 || i >= grid.size() || j < 0 || j >= grid[0].size())
return ; //超出边界
grid[i][j] = '2'; //标记访问过
dfs(grid, i+1, j);
dfs(grid, i-1, j);
dfs(grid, i, j+1);
dfs(grid, i, j-1);
largest-rectangle-in-histogram
给定n个非负整数,用来表示柱状图中各个柱子的高度,每个柱子彼此相邻,且宽度为1,求在该柱状图中,能勾勒出来的矩形的最大面积。
思路:求当前柱子为高度的最大面积,即转化为寻找小于当前值的左右两边值
用到了单调栈
int largestRectangleArea(vector<int>& heights)
//基于各个高度的最大矩形是在出栈的时候计算,所以必须让所有高度都出栈
//利用单调栈的性质,在原始数组后添加一个0
heights.push_back(0);
stack<int> s; //栈
int maxArea = 0;
for(int i = 0; i < heights.size(); i++)
while(!s.empty() && heights[i] < heights[s.top])
int h = heights[s.top()];
s.pop();
int w = s.empty() ? i : i - s.top() - 1;
maxArea = max(maxArea, h*w);
s.push(i);
return maxArea;
队列
常用于BFS宽度搜索
常见题型:
implement-queue-using-stacks
使用两个栈实现队列
class MyQueue
public:
stack<int> inStack;
stack<int> outStack;
MyQueue()
void push(int x)
inStack.push(x);
int pop()
cheak(); //将inStack栈内元素移动到outStack
int top = outStack.top();
outStack.pop();
return top;
int peek()
//得到队首元素
cheak();
return outStack.top();
bool empty()
return inStack.empty() && outStack.empty();
void cheak()
if(outStack.empty())
while(!inStack.empty())
outStack.push(inStack.top());
inStack.pop();
;
二叉树层次遍历模板
vector<vector<int>> levelOrder(TreeNode* root)
vector<vector<int>> res;
if(root == NULL) return res;
queue<TreeNode*> q;
q.push(root);
while(!q.empty())
int size = q.size();
res.push_back(vector<int>());
for(int i = 0; i < size; i++)
TreeNode *top = q.front();
res.back().push_back(top->val);
q.pop();
if(top->left) q.push(top->left);
if(top->right) q.push(rop->right);
return res;
给定一个由0和1组成的矩阵,找出每个元素到最近的0的距离,两个相邻元素间的距离是1
01矩阵问题,采用BFS方法求解
从0进入队列,弹出之后计算上下左右的结果,将上下左右重新进队列进行二层操作
vector<vector<int>> updateMatrix(vector<vector<int>>& matrix)
int row = matrix.size(), col = matrix[0].size();
vector<pair<int,int>> directions = 0, 1, 0, -1, 1, 0, -1, 0;
vector<vector<int>> res(row, vector<int>(col, INT_MAX));
queue<pair<int, int>> q;
for(int i = 0; i < row; i++)
for(int j = 0; j < col; j++)
if(matrix[i][j] == 0)
res[i][j] = 0;
q.push(i, j);
while(!q.empty())
auto temp = q.front();
q.pop();
for(int i = 0; i < 4; i++)
int x = temp.first + directions[i].first;
int y = temp.second + directions[i].second;
if(x >= 0 && x < row && y >= 0 && y <= col)
// 保证在边界内
if(res[x][y] > res[temp.first][temp.second] + 1)
res[x][y] = res[temp.first][temp.second] + 1;
q.push(x, y);
return res;
总结
- 知道栈的使用场景
- 先入后出,保存临时值
- 利用栈实现DFS
- 熟悉队列的使用场景
- 利用队列实现BFS
以上是关于算法模板-----栈和队列的主要内容,如果未能解决你的问题,请参考以下文章