s representing a valid expression, implement a basic calculator to evaluate it, and return the result of the evaluation.Note: You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as
eval().
Example 1:
Input: s = "1 + 1" Output: 2Example 2:
Input: s = " 2-1 + 2 " Output: 3Example 3:
Input: s = "(1+(4+5+2)-3)+(6+8)" Output: 23
Constraints:
- 1 <= s.length <= 3 * 105
- sconsists of digits,- '+',- '-',- '(',- ')', and- ' '.
- srepresents a valid expression.
- '+'is not used as a unary operation (i.e.,- "+1"and- "+(2 + 3)"is invalid).
- '-'could be used as a unary operation (i.e.,- "-1"and- "-(2 + 3)"is valid).
- There will be no two consecutive operators in the input.
- Every number and running calculation will fit in a signed 32-bit integer.
递归。
每当遇到了 ( , 就去找到其对应的) ,然后里面包含的字符串就递归调用本身
class Solution {
public:
    int calculate(string s) {
        int res =0, start = 0;
        vector<string> V;
        while(start < s.size()){
            if(s[start] == ' '){
                start ++;
            }else if(s[start] == '-' || s[start] == '+'){
                V.push_back(s.substr(start,1));
                start++;
            }else if(s[start] == '('){
                // find ending '('
                int nDiff = 1; // count of (  - count of )
                int end = start;
                while(nDiff > 0 && end < s.size()){
                    end++; // Must increase here, bottom within while is wrong
                    if(s[end] == '('){
                        nDiff++;
                    }else if(s[end] == ')'){
                        nDiff--;
                    }
                }
                int val = calculate(s.substr(start+1, end- start-1));
                start = end +1;
                V.push_back(to_string(val));
            }else if(isdigit(s[start]) ){
                int end = start;
                while(isdigit(s[end]) && end < s.size()){
                    end++;
                }
                V.push_back(s.substr(start, end-start));
                start = end;
            }
        }
        // need to check first .
        start = 0;
        if(V[0] != "-"){ 
            res = stoi(V[0]);
            start = 1;
        }
        for(int i =start; i<V.size(); i+= 2){
            if(V[i]=="-"){
                res -= stoi(V[i+1]);
            }else{
                res += stoi(V[i+1]);
            }
        }
        return res;
    }
};
Pass了,但是代价就是beat了不到10%
改进, 利用& 和 起止的index 作为参数传递给函数。 然而测试后并没有什么改善。可见消耗的时间更多的是在把n层的()要跑n遍上。 
因此还是要用stack 呀
Error:
in C++,
         char ch = '-';
         std::cout<< std::to_string(ch);
会打印 45.  而不是"-"  
因为 
std::to_string(ch) expects a number, not a character.需要用Stack.  但是考虑到每个()都是独立的,因此遇到( 就是新的一层, 遇到)就计算并删掉最高的一层。     ---------》 只是最终结果也只是比上面好了一点点。 beat 10% 不到
**************错误就是出在每次都要substring上***************
别人的代码
Mistakes:
1: 自己的解法有个最需要注意的问题就是: pop完了()两个运算符之后,要再 调用check(),因为我们相当于重新加入了一个运算数了
————————————————————————————————————
第一个解法,会造成某个数字是负数。再代入的话,就破坏原题目的简洁了
另外, 可能有多个括号并列的情况存在。
class Solution {
public:
    int calculate(string s) {
        // use stack of vectors. when see ( go upper layer, and when see )
        // calculate top layer, and append result to lower layer
        stack<vector<string>> S;
        S.push(vector<string>{}); // need make first layer
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '-' || s[i] == '+') {
                S.top().push_back(s.substr(i, 1));
            } else if (s[i] == '(') {
                S.push(vector<string>{});
            } else if (s[i] == ')') {
                int val = helper(S.top());
                S.pop();
                S.top().push_back(to_string(val));
            } else if (isdigit(s[i])) {
                int end = i;
                while (isdigit(s[end]) && end < s.size()) {
                    end++;
                }
                S.top().push_back(s.substr(i, end - i));
                i = end - 1; // since we have i++ in the for loop
            }
        }
        return helper(S.top());
    }
private:
    int
    helper(const vector<string>& V) { // without (), calculate only += digits
        int start = 0, res = 0;
        if (V[0] != "-") { // first check if start with a number or -
            res = stoi(V[0]);
            start = 1;
        }
        for (int i = start; i < V.size(); i += 2) {
            if (V[i] == "-") {
                res -= stoi(V[i + 1]);
            } else {
                res += stoi(V[i + 1]);
            }
        }
        return res;
    }
};
**************错误就是出在每次都要substring上***************
别人的代码
public class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(1);
        int res = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (Character.isDigit(c)) {
                int num = c - '0';
                int j = i + 1;
                while (j < s.length() && Character.isDigit(s.charAt(j))) {
                    num = 10 * num + (s.charAt(j) - '0');
                    j++;
                }
                res += stack.pop() * num;
                i = j - 1;
            } else if (c == '+' || c == '(') {
                stack.push(stack.peek());
            } else if (c == '-') {
                stack.push(-1 * stack.peek());
            } else if (c == ')') {
                stack.pop();
            }
        }
        return res;
    }
}
Mistakes:
1: 自己的解法有个最需要注意的问题就是: pop完了()两个运算符之后,要再 调用check(),因为我们相当于重新加入了一个运算数了
————————————————————————————————————
第一个解法,会造成某个数字是负数。再代入的话,就破坏原题目的简洁了
另外, 可能有多个括号并列的情况存在。
 
No comments:
Post a Comment