[算法专题] 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