The basic idea of an IS as follows:
- maintain a deque
operands
for The numbers and another deque operations
for the operators +,-, *,
/'.
- Scan the expression from left to right, each time we meet a digit, extract the whole number with and after it, push th E number into
operands
.
- If we meet
*
or /
, we extract the next number in the expression and the last Number in operands
, compute the intermediate result of them and store the result into operands.
- If we meet
+
or -
, we store it into operations
. - after scanning the whole expression, we visit
operations
from Front to back and perform the Ope Rations with the corresponding elements (each time with the first, elements in operands
).
Let's see a concrete example and run the above process. Suppose we want calculate 1-2*3+4
, we'll first push 1
into operands, < code>- into Operations and then 2
into operands. Then we meet *
, which have higher priority over +
and -
. We take 2
out from operands
and extract the next operand 3 /code> and multiply them, obtaining 6
. We push 6
into operands
. Then we push +
into operations
and 4
into operands .
So, after the scanning of the expression, operands
will be [1, 6, 4]
, operations
will be [-, +]
. The remaining computation is 1-6+4
. We perform it from front to back. Specifically, we take 1
and 6
out from operands
and -
out from operations
and perform 1-6 = 5
and push 5
into operands.
Now are and is operands
[-5, 4]
operations
[+]
. We simply repeat the above process and perform -5+4=-1
. We push -1
into operands
. Finally, is and is operands
[-1]
operations
empty. Now the remaining a is the operands
result and we were done.
In a word, my solution breaks down the original expression into additions and subtractions and compute multiplications and Divisions first while scanning the expression.
The idea-to-use deque is if we perform step 2, we need to know the last element of We push operands
to, which are like the Top of a stack. Moreover, when we are perform step 5, we need to know the first element we push operands
to, which are like the front of a queue. Due to this double-ended structure (we need to being able to access the last added and first added element), a deque is a NAT Ural choice.
The code is as follows.
1 classSolution {2 Public:3 intCalculatestrings) {4deque<int>operands;5deque<Char>operations;6 for(inti =0; I < (int) s.length (); i++) {7 if(IsDigit (S[i])) {8 intnum =Extract_num (S, i);9 operands.push_back (num);Ten } One Else if(S[i] = ='*'|| S[i] = ='/') { A CharOP =S[i]; - intFirst =Operands.back (); - Operands.pop_back (); thei++; - while(!isdigit (S[i])) i++; - intSecond =Extract_num (S, i); - if(OP = ='*') +Operands.push_back (First *second); - ElseOperands.push_back (First/second); + } A Else if(S[i] = ='+'|| S[i] = ='-') at Operations.push_back (S[i]); - } - while(!Operations.empty ()) { - CharOP =Operations.front (); - Operations.pop_front (); - intFirst =Operands.front (); in Operands.pop_front (); - intSecond =Operands.front (); to Operands.pop_front (); + if(OP = ='+') -Operands.push_front (First +second); the ElseOperands.push_front (First-second); * } $ returnOperands.front ();Panax Notoginseng } - Private: the intExtract_num (string& S,int&i) { + intnum =0; A while(I < (int) s.length () &&isdigit (S[i])) thenum = num *Ten+ s[i++]-'0'; +i--; - returnnum; $ } $};
Of course, there is still much redundancy in the above code. In fact, there are no need to use any Deque-like data structure to store all the numbers or operators. We can simply solve it in O (1) space. A Nice solution are at the this link. I have rewritten it below.
1 classSolution {2 Public:3 intCalculatestrings) {4 inti =0, res =0, sign =1;5 intnum =Extract_num (S, i);6 while(I < (int) s.length ()) {7 if(S[i] = ='+'|| S[i] = ='-') {8 CharOP =S[i];9res + = num *Sign ;Tennum = Extract_num (s, + +i); OneSign = (OP = ='+'?1: -1); A } - Else if(S[i] = ='*') -Num *= Extract_num (s, + +i); the Else if(S[i] = ='/') -Num/= Extract_num (s, + +i); - } -res + = num *Sign ; + returnRes; - } + Private: A intExtract_num (string& S,int&i) { at intnum =0; - while(I < (int) s.length ()) { - if(IsDigit (s[i])) num = num *Ten+ S[i]-'0'; - Else if(S[i]! =' ')returnnum; -i++; - } in returnnum; - } to};
[Leetcode] Basic Calculator II