1. Stack


什么情况使用栈?
  1. 利用栈的后进先出性质。
  2. 输入:数组,输出:与数组下标和元素都相关。而且栈中构成一定的顺序比如递增、递减,如果不满足则出栈进行计算。
需要注意的情况
  1. 搞清楚什么时候需要入栈、出栈
  2. 搞清楚栈中应该放元素or下标
  3. 什么时候更新结果
42和84一样的题就是求最大/求和的区别。他们2个和32题很像,相同点:
  1. 都是求最大值,结果范围不确定。
  2. 到达某个点之后满足条件对栈顶出栈进行操作,更新最大值。
  3. 都是通过栈保存数组下标,一遍求范围或宽度。
  4. 遍历过程中栈会出栈导致下标不连续从而求出范围。
不同点:
  1. 32题只是求一维的范围,而84题求下标范围和对应数组中值的乘积,属于二维。然而时间复杂度都是O(n)。
  2. 32题中入栈操作是遍历到'('或者')'但是栈中为空或栈顶不是'('时,而84题每次都会入栈。
  3. 出栈条件不同,32题为新元素为')'且栈顶为'(',if语句;而84题为新元素的高度小于栈顶,语句为while。

150. Evaluate Reverse Polish Notation
描述:在逆波兰记法中,所有操作符置于操作数的后面,因此也被称为后缀表示法
思路:对vector从左到右进行遍历,每次遇到数字就放入栈中,每次遇到运算符就从栈中取出2个数字并使用该运算符对这2个数字进行运算,结果再放入栈中。最后栈中应该只剩1个元素,该元素就是结果。
Time:O(n) Space:O(n)
int evalRPN(vector<string>& tokens) {
    stack<int> operands;
    set<string> operator_set = {"+", "-", "*", "/"};
    
    for (auto to:tokens) {
        if (operator_set.find(to) != operator_set.end()) {
            int right = operands.top();
            operands.pop();
            int left = operands.top();
            operands.pop();
            if (to == "+") operands.push(left + right);
            else if (to == "-") operands.push(left - right);
            else if (to == "*") operands.push(left * right);
            else if (to == "/") operands.push(left / right);
        } else {
            operands.push(stoi(to));
        }
    }
    
    return operands.top();
}

20. Valid Parentheses
描述:包含三种括号,是否满足左开右闭。
思路:使用栈保存左边的,出现右边时进行判断若栈顶和该右括号恰好抵消则出栈。
Time:O(n) Space:O(n)
bool isValid(string s) {
    stack<char> parentheses;
    unordered_map<char, char> left2right = {{'\(', '\)'}, {'\{', '\}'}, {'\[', '\]'}};
    for (char c:s) {
        if (c == '\(' || c == '\{' || c == '\[') {
            parentheses.push(c);
        } else if (!parentheses.empty() && c == left2right[parentheses.top()]) {
            parentheses.pop();
        } else{
            return false;
        }
    }
    return parentheses.empty();
}

32. Longest Valid Parentheses
描述:一个只包含左括号'('和右括号')'的string中,求满足左开右闭的最大长度
思路:使用栈记录每个左括号和未命中的右括号的位置,每次遇到可以命中的右括号则取出栈顶并更新最大长度。
Time:O(n) Space:O(n)
int longestValidParentheses(string s) {
    stack<int> s_pos;
    int res = 0;
    for (auto i = 0; i < s.size(); ++i) {
        if (!s_pos.empty() && s[i] == '\)' && s[s_pos.top()] == '\(') {
            s_pos.pop();
            int last_pos = -1;
            if (!s_pos.empty()) last_pos = s_pos.top();
            res = max(res, i - last_pos);
        } else {
            s_pos.push(i);
        }
    }
    return res;
}

84. Largest Rectangle in Histogram
描述:直方图中找出面积最大的长方形
思路:将vector的下标存放在栈中。栈顶存放的下标是栈中最高的,当当前高度比栈顶的低时,找出栈顶高度适合的宽度(比栈顶低下标,不一定连续),这样就保证了缺失部分都是>=栈顶高度的。栈中保存下标对应高度是递增的,中间缺失部分为高于2边的情况。
int largestRectangleArea(vector<int>& heights) {
    int res = 0;
    stack<int> pos_stack;
    heights.push_back(0);
    
    for (auto i = 0; i < heights.size(); ++i) {
        while (!pos_stack.empty() && 0. >= heights[i]) {
            int h = heights[pos_stack.top()];
            pos_stack.pop();
            
            int last_pos = -1;
            if (!pos_stack.empty()) last_pos = pos_stack.top();
            res = max(res, h*(i - last_pos - 1));
        }
        pos_stack.push(i);
    }
    
    return res;
}

42. Trapping Rain Water
描述:几个柱状体的盛水大小
思路:最优肯定是使用左右记录最大高度。使用栈也可以做,便于理解。 入栈:只有<=栈顶的元素才入栈。出栈:当元素>栈顶时,栈顶做bottom并出栈,比较该栈顶2遍高度选取小的与bottom做差并求出面积。
Time:O(n) Space:O(n)
int trap(vector<int>& height) {
    if (height.size() < 3) return 0;
    int res = 0;
    stack<int> height_pos;
    
    for (int i = 0; i < height.size(); ++i) {
        while (!height_pos.empty() && height[i] > height[height_pos.top()]) {
            int bottom = height[height_pos.top()];
            height_pos.pop();
            
            if (!height_pos.empty()) {
                res += (min(height[height_pos.top()], height[i]) - bottom)*(i - height_pos.top() - 1);
            }
        } 
        height_pos.push(i);
    }
    return res;
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容

  • 在Xcode7中,如果你注意的话,在菜单栏中Editor下拉列表中没有了Pin这个选项.如图1-6-1 而相反的在...
    乐编阅读 508评论 0 0
  • 课程介绍 先修课:概率统计,程序设计实习,集合论与图论 后续课:算法分析与设计,编译原理,操作系统,数据库概论,人...
    ShellyWhen阅读 2,222评论 0 3
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,712评论 0 33
  • leetcode刷题记录本文记录一下leetcode刷题记录,记录一下自己的解法和心得。 LeetCode Two...
    EarthChen阅读 3,419评论 0 6
  • 别人对我好一点 我便开始惶恐与焦虑 拿什么回报 怎样做才不辜负期望 别人对我差一点 我便开始反省与自责 做错了什么...
    蜗牛sister阅读 203评论 2 4