[算法专题] stack

1. Convert Expression to Reverse Polish Notation

http://www.lintcode.com/en/problem/convert-expression-to-polish-notation/

Given an expression string array, return the Polish notation of this expression. (remove the parentheses)

Example

For the expression [(5 ? 6) * 7] (which represented by ["(", "5", "?", "6", ")", "*", "7"]), the corresponding polish notation is [* - 5 6 7] (which the return value should be ["*", "?", "5", "6", "7"]).

Algorithm
1. Scan the infix expression from left to right.
2. If the scanned character is an operand, output it.
3. Else,
…..3.1 If the precedence of the scanned operator is greater than the precedence of the operator in the stack(or the stack is empty), push it.
…..3.2 Else, Pop the operator from the stack until the precedence of the scanned operator is less-equal to the precedence of the operator residing on the top of the stack. Push the scanned operator to the stack.
4. If the scanned character is an ‘(‘, push it to the stack.
5. If the scanned character is an ‘)’, pop and output from the stack until an ‘(‘ is encountered.
6. Repeat steps 2-6 until infix expression is scanned.
7. Pop and output from the stack until it is not empty.

代码如下:

class Solution {
public:
    /**
     * @param expression: A string array
     * @return: The Reverse Polish notation of this expression
     */
    vector<string> convertToRPN(vector<string> &exp) {
        vector<string> vec;
        stack<string> st;

        for (int ix = 0; ix != exp.size(); ix++) {
            if (isDigit(exp[ix])) {
                vec.push_back(exp[ix]);
            } else if (exp[ix] == "(") {
                st.push(exp[ix]);
            } else if (exp[ix] == ")") {
                while (st.top() != "(") {
                    vec.push_back(st.top());
                    st.pop();
                }
                st.pop(); // pop "("
            } else {
                while (!st.empty() && pri(exp[ix]) <= pri(st.top())) {
                    vec.push_back(st.top());
                    st.pop();
                }

                st.push(exp[ix]);
            }
        }

        while (!st.empty()) {
            vec.push_back(st.top());
            st.pop();
        }

        return vec;
    }

private:
    int isDigit(const string &s) {
        size_t len = s.size();
        string start(len, ‘0‘);
        string end(len, ‘9‘);
        return start <= s && s <= end;
    }

    int pri(const string &s) {
        if (s == "+" || s == "-") {
            return 1;
        } else if (s == "*" || s == "/") {
            return 2;
        }

        return -1;
    }
};

2. Expression Evaluation

http://www.lintcode.com/en/problem/expression-evaluation/#

Given an expression string array, return the final result of this expression

Example

For the expression 2*6-(23+7)/(1+2), input is

[
  "2", "*", "6", "-", "(",
  "23", "+", "7", ")", "/",
  (", "1", "+", "2", ")"
],

return 2

Following is algorithm for evaluation postfix expressions.

1) Create a stack to store operands (or values).

2) Scan the given expression and do following for every scanned element.

…..a) If the element is a number, push it into the stack

…..b) If the element is a operator, pop operands for the operator from stack. Evaluate the operator and push the result back to the stack

3) When the expression is ended, the number in the stack is the final answer

Example:

Let the given expression be “2 3 1 * + 9 -“. We scan all elements one by one.

1) Scan ‘2’, it’s a number, so push it to stack. Stack contains ‘2’

2) Scan ‘3’, again a number, push it to stack, stack now contains ‘2 3′ (from bottom to top)

3) Scan ‘1’, again a number, push it to stack, stack now contains ‘2 3 1′

4) Scan ‘*’, it’s an operator, pop two operands from stack, apply the * operator on operands, we get 3*1 which results in 3. We push the result ‘3’ to stack. Stack now becomes ‘2 3′.

5) Scan ‘+’, it’s an operator, pop two operands from stack, apply the + operator on operands, we get 3 + 2 which results in 5. We push the result ‘5’ to stack. Stack now becomes ‘5’.

6) Scan ‘9’, it’s a number, we push it to the stack. Stack now becomes ‘5 9′.

7) Scan ‘-‘, it’s an operator, pop two operands from stack, apply the – operator on operands, we get 5 – 9 which results in -4. We push the result ‘-4′ to stack. Stack now becomes ‘-4′.

8) There are no more elements to scan, we return the top element from stack (which is the only element left in stack).

即遍历后缀表达式,遇到数字入栈,遇到operator弹栈计算,并将计算结果入栈,当遍历完后缀表达式后,栈顶元素即为返回值。代码如下:

#include <stdlib.h>
class Solution {
public:
    /**
     * @param expression: a vector of strings;
     * @return: an integer
     */
    int evaluateExpression(vector<string> &exp) {
        if (exp.empty()) {
            return 0;
        }

        vector<string> post = convertToRPN(exp);
        stack<int> st;
        for (int ix = 0; ix != post.size(); ix++) {

            if (isDigit(post[ix])) {
                st.push(atoi(post[ix].c_str()));
            } else {

                    int right = st.top(); st.pop();
                    int left = st.top(); st.pop();
                    int res = calculate(left, right, post[ix]);
                    st.push(res);

            }
        }

        return st.top();
    }

private:
    int calculate(int left, int right, const string &oper) {

        if (oper == "+") {
            return left + right;
        } else if (oper == "-") {
            return left - right;
        } else if (oper == "*") {
            return left * right;
        } else {
            return left / right;
        }
    }

    vector<string> convertToRPN(vector<string> &exp) {
        vector<string> vec;
        stack<string> st;

        for (int ix = 0; ix != exp.size(); ix++) {
            if (isDigit(exp[ix])) {
                vec.push_back(exp[ix]);
            } else if (exp[ix] == "(") {
                st.push(exp[ix]);
            } else if (exp[ix] == ")") {
                while (st.top() != "(") {
                    vec.push_back(st.top());
                    st.pop();
                }
                st.pop(); // pop "("
            } else {
                while (!st.empty() && pri(exp[ix]) <= pri(st.top())) {
                    vec.push_back(st.top());
                    st.pop();
                }

                st.push(exp[ix]);
            }
        }

        while (!st.empty()) {
            vec.push_back(st.top());
            st.pop();
        }

        return vec;
    }

    int isDigit(const string &s) {
        size_t len = s.size();
        string start(len, ‘0‘);
        string end(len, ‘9‘);
        return start <= s && s <= end;
    }

    int pri(const string &s) {
        if (s == "+" || s == "-") {
            return 1;
        } else if (s == "*" || s == "/") {
            return 2;
        }

        return -1;
    }
};

3. Valid Parentheses

http://www.lintcode.com/en/problem/valid-parentheses/#

Given a string containing just the characters ‘(‘, ‘)‘, ‘{‘,‘}‘, ‘[‘ and ‘]‘, determine if the input string is valid.

Example

The brackets must close in the correct order, "()" and"()[]{}" are all valid but "(]" and "([)]" are not.

class Solution {
public:
    /**
     * @param s A string
     * @return whether the string is a valid parentheses
     */
    bool isValidParentheses(string& s) {
        stack<char> st;
        for (string::const_iterator itr = s.begin(); itr != s.end(); itr++) {

            if (st.empty()) {
                st.push(*itr);
            } else if (consist(st.top(), *itr)) {
                st.pop();
            } else {
                st.push(*itr);
            }

        }

        return st.empty();
    }

private:

    bool consist(const char left, const char right) {
        switch(left) {
            case ‘(‘ :
                return right == ‘)‘;
            case ‘[‘ :
                return right == ‘]‘;
            case ‘{‘ :
                return right == ‘}‘;
        }
    }
};

4

 

时间: 2024-10-22 20:02:49

[算法专题] stack的相关文章

[算法专题] LinkedList

前段时间在看一本01年出的旧书<effective Tcp/Ip programming>,这个算法专题中断了几天,现在继续写下去. Introduction 对于单向链表(singly linked list),每个节点有?个next指针指向后一个节点,还有一个成员变量用以储存数值:对于双向链表(Doubly LinkedList),还有一个prev指针指向前一个节点.与数组类似,搜索链表需要O(n)的时间复杂度,但是链表不能通过常数时间读取第k个数据.链表的优势在于能够以较?的效率在任意位

【枚举算法Day1】20170529-2枚举算法专题练习

20170529-2枚举算法专题练习 青岛二中日期 序号 题目名称 输入文件名 输出文件名 时限 内存 算法 难度 分类 081113 1 最大矩形 rectangle.in rectangle.out 1s 256MB 枚举 1 02枚举 081031 2 回文 palin.in palin.out 1s 256MB 枚举.优化 1 02枚举 081008 3 问题的设置 problemsetter.in problemsetter.out 1s 256MB 排序+枚举 1 02枚举 0810

图的算法专题——最短路径

概要: Dijkstra算法 Bellman-Ford算法 SPFA算法 Floyd算法 1.Dijkstra算法用于解决单源最短路径问题,严格讲是无负权图的最短路径问题. 邻接矩阵版 1 const int maxv=1000; 2 const int INF=1000000000; 3 int n,G[maxv][maxv]; 4 int d[maxv]; //起点到各点的最短路径长度 5 bool vis[maxv]={false}; 6 7 void Dijkstra(int s){ /

括号匹配问题 -算法专题

算法数据结构面试分享 符号匹配问题 今天在帖子上看见有同学在问,如果一个字符串中包含大括号和小括号,我们该如何解决括号匹配问题.我们今天就一起看下这道题吧.按照我们之前的套路,按部就班来: 确保我们理解了问题,并且尝试一个例子,确认理解无误. 举个例子,这样的括号是匹配的, ().{}.({}), ({()}(){}), 而类似于{(.{,({)都是不匹配的. 想想你可以用什么方法解决问题,你会选择哪一种,为什么? 我们拿这个字符串为例,({()}(){}), 最后一个)匹配的是第一个(, 倒数

最短路径算法专题1----弗洛伊德

由于最短路径算法我认为比较重要,所以分成几个专题来慢慢细化去磨它,不能一口气吃个胖子嘛. 首先在说算法之前,先说清楚什么叫做最短路径. 题目一般会给你一张图,然后告诉你很多地方,然后告诉你各个地方之间的路程有多远,要你求出,两点间的最短距离,注意,题目给出的两点间的距离未必是最短的,可能通过第三个点转换之后达到更短.实际其实也是这样的,有时候两个地方并没有直线的道路只有曲线的绕路. 算法的思路: 1.用二维数组列出所有的距离,达到不了的用最大距离表示,如9999999 2.循环数组上面的每一个点

ACM&amp;OI 基础数学算法专题

[前言] 本人学习了一定时间的算法,主要精力都花在数学类的算法上面 而数学类的算法中,本人的大部分精力也花费在了数论算法上 此类算法相对抽象,证明过程比较复杂 网络上的博客有写得非常好的,但也有写得不明所以的 因此,本人特此开一个新的专题,专门负责讲解一些比较基础的数学类算法 但本人知识面也有限,部分算法也还未掌握.因此,希望本专题也能促进本人学习这些算法 下面做出对更新的一些规定: 基本上保持每日更新一贴 对标注(已完结)的贴子,表明本贴子已完结 对标注(正在更新)的贴子,表明正在更新本贴 对

KM算法专题

原文:http://972169909-qq-com.iteye.com/blog/1184514 题目地址:这里. 1)求图中所有环的总长度(环的长度不唯一)的最小值.当无法得到完备匹配时说明环不存在. 第三题:http://acm.hdu.edu.cn/showproblem.php?pid=1853 直接建图,注意有重边哦! if (-c > w[a][b])     w[a][b] = -c; 当木有完美匹配输出-1 第四题:http://acm.hdu.edu.cn/showprobl

最短路径算法专题2----Dijkstra

这个算法适用于求单源最短路径,从一点出发,到其余个点的最短路径. 算法要点: 1.用二维数组存放点到点的距离-----不能相互到达的点用MAX代替距离 2.用dis数组存放源点到任意其他一点的距离----dis[5]表示源点到5点的距离为dis[5]中的值 3.用book数组记录已经确定最小dis的点 4.用index和indexNumber存放估计值的点 5.从源点到这个点如果比中间加上估计值的点还要长,就松弛 算法模型: for(循环N次) { for(循环找到估计值点) { 估计值点是现在

排序算法专题

数据结构课程可能会考到的排序算法: 插入排序 希尔排序 冒泡法 快排 选择排序 堆排序 归并排序 一 插入排序 #include<cstdio> #include<string> #include<cstring> #include<iostream> using namespace std; void print(int a[], int n ,int i) { cout<<i <<":"; for(int j=