栈与DFS

栈的应用举例:最小栈[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;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值