栈的应用举例:最小栈[155]
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
// 对象声明
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.top(); --> 返回 -3.
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
minStack.pop();
minStack.top(); --> 返回 -2.
minStack.getMin(); --> 返回 -2.
class MinStack {
private:
// 设置两个栈一个用来存储原值,一个用来存储其下方的最小值
stack<int> x_stack;
stack<int> min_stack;
public:
/** initialize your data structure here. */
// 防止比较出现堆溢出报错,先在最小栈底压入INT_MAX
MinStack() {
min_stack.push(2147483647);
}
// 压入
void push(int x) {
x_stack.push(x);
min_stack.push(min(min_stack.top(), x));
}
//弹出
void pop() {
x_stack.pop();
min_stack.pop();
}
//当前栈顶值
int top() {
return x_stack.top();
}
//当前栈内最小值
int getMin() {
return min_stack.top();
}
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(x);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
例题
有效的括号[20]
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
单调栈
将元素的索引压入栈,根据索引所调用的元素值进行条件比较
下一个更大的值[496]
给定两个 没有重复元素 的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。
输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。
class Solution {
public:
vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
if(!len1) return {};
int len2 = nums2.size();
// 一、先对nums2使用单调栈获得各元素的下一最大值
vector<int> ans2(len2, -1);
stack<int> s;
for(int i=0; i<len2; i++){
// 遇到比栈顶索引所指的元素大的元素时,则保存至栈顶索引位置的容器中
while(!s.empty() && nums2[s.top()]<nums2[i]){
ans2[s.top()] = nums2[i];
s.pop();
}
// 压入新索引
s.push(i);
}
// 二、再对nums1在nums2上遍历,找到元素相同的索引,读取其下一最大值
vector<int> ans1(len1, -1);
for(int i=0; i<len1; i++){
int id;
for(int j=0; j<len2; j++){
if(nums1[i]==nums2[j]){
id = j;
ans1[i] = ans2[j];
break;
}
}
}
return ans1;
}
};
升温等待时间[739]
请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。
输入:temperatures = [73, 74, 75, 71, 69, 72, 76, 73],
输出: [1, 1, 4, 2, 1, 1, 0, 0]。
class Solution {
public:
vector<int> dailyTemperatures(vector<int>& T) {
int len = T.size();
if(!len) return {};
stack<int> s;
vector<int> ans(len, 0);
// 各元素分别比较后再压入其对应索引
for(int i=0; i<len; i++){
while(!s.empty() && T[s.top()] < T[i]){
ans[s.top()] = i-s.top();
s.pop();
}
s.push(i);
}
return ans;
}
};
从起始点是否可以访问所有点
[841]
法一:深度优先遍历
class Solution {
public:
// 记录访问情况
vector<int> vis;
// 记录访问房间的数量
int num;
//
void dfs(vector<vector<int>>& rooms, int x) {
// 记录该房间为被访问
vis[x] = 1;
// 进入房间+1
num++;
// 遍历该房间的各钥匙
for (auto& it : rooms[x]) {
// 判断防止重复访问
if (!vis[it]) {
dfs(rooms, it);
}
}
}
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
num = 0;
// 确定房间的数量
vis.resize(n);
dfs(rooms, 0);
return num == n;
}
};
法二:广度优先遍历
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
// 记录访问情况
vector<int> vis(n, 0);
// 设置队列(bfs惯例)
queue<int> q;
// 记录并压入起始信息
vis[0] = 1;
int num = 1;
int door;
q.push(0);
// bfs
while(!q.empty()){
door = q.front();
q.pop();
for(auto& it : rooms[door]){
// 仅压入未被访问的空间信息
if(!vis[it]){
// 访问新空间后,数量更新
num++;
q.push(it);
vis[it] = 1;
}
}
}
return num == n;
}
};
二叉树的所有路径
[257]LeetCode
给定一个二叉树,返回所有从根节点到叶子节点的路径。
说明: 叶子节点是指没有子节点的节点。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
法一:深度优先搜索
从根节点开始的先序遍历
条件判断1:当前根节点是否存在
条件判断2:当前是否为叶子节点
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
tranversal(root, "", res);
return res;
}
void tranversal(TreeNode* root, string buff, vector<string>& res){
if(root != nullptr){
buff += to_string(root->val);
if(root->left == nullptr &&root->right==nullptr){
res.push_back(buff);
}else{
buff += "->";
tranversal(root->left, buff, res);
tranversal(root->right, buff, res);
}
}
}
};
法二:广度优先搜索
设计队列1进行节点的遍历
设计队列2进行路径的更新
class Solution {
public:
vector<string> binaryTreePaths(TreeNode* root) {
vector<string> res;
if(root == nullptr) return res;
queue<TreeNode*> node;
queue<string> buff;
node.push(root);
buff.push(to_string(root->val));
while(!node.empty()){
TreeNode* curnode = node.front();
string curbuff = buff.front();
node.pop();
buff.pop();
if(curnode->left != nullptr){
node.push(curnode->left);
buff.push(curbuff + "->"+ to_string(curnode->left->val));
}
if(curnode->right != nullptr){
node.push(curnode->right);
buff.push(curbuff + "->"+ to_string(curnode->right->val));
}
if(curnode->left==nullptr && curnode->right==nullptr){
res.push_back(curbuff);
}
}
return res;
}
};