1: class Solution { 2: public: 3: vector<string> addOperators(string num, int target) { 4: vector<string> res; 5: if (num.empty()) return res; 6: dfs(num, target, "", res, 0, 0, 0); 7: return res; 8: } 9: void dfs(string &num, int target, string sol, vector<string> &res, int start, long long cur, long long prev) { 10: if (start == num.size()) { 11: if (target == cur) res.push_back(sol); 12: return; 13: } 14: for (int i = start; i < num.size(); i++) { 15:if (num[start] == '0' && i > start) break;16: string s = num.substr(start, i-start+1); 17: // when dealing with string, be sure to use long long. 18: long long val = stol(s); 19:if (start == 0) {20: // special case for first digit. 21: dfs(num, target, s, res, i+1, val, val); 22: } else { 23: dfs(num, target, sol+"+"+s, res, i+1, cur+val, val); 24: dfs(num, target, sol+"-"+s, res, i+1, cur-val, -val); 25: dfs(num, target, sol+"*"+s, res, i+1, cur-prev+prev*val, prev*val); 26: } 27: } 28: } 29: };
Showing posts with label overflow. Show all posts
Showing posts with label overflow. Show all posts
Saturday, July 9, 2016
282. Expression Add Operators
My intuition is dfs. For each dfs, try one digit, two digits until the whole number. For each number, we compute the value. We take the computational value so far, do the addition, subtraction and production respectively. Addition and subtraction are straightforward, but production requires a little trick. Take "a+b*c" as example, at position 'c', the computational value so far is "a+b", so we need subtract b and add product of b and c. Therefore, we need to track the value for previous operation. So far, the api requires two more additional arguments: computational value so far and value for previous operation. Note, we don't have to do any operation for first number so we need to take it as special case. Also, since the number is converted from string, it's very easy to get overflow. So we must use long integer. Finally, "08" is not a valid number and we need to take care of this case. As a result, the code is as following.
Tuesday, July 5, 2016
166. Fraction to Recurring Decimal
The trick to solve this problem is to get the recurring numbers. Since we don't know when recurring happens, for example, 4/333 = 0.(012) and 1/6 = 0.1(6), we have to record all the remainders that we have seen before. We can use hash map here to retrieve the previous remainders fast. Also, once we find the recurring remainder, we need to insert a left parenthesis before it so the key-value pair of the hash map is remainder-position.
Besides these, we need to take care of overflow which can be solved by long long and the negative number which we need a prefix "-".
Besides these, we need to take care of overflow which can be solved by long long and the negative number which we need a prefix "-".
1: class Solution {
2: public:
3: string fractionToDecimal(int numerator, int denominator) {
4: if (!numerator) return "0";
5: int sign = (numerator < 0) ^ (denominator < 0) ? -1 : 1;
6: string res = (sign == -1) ? "-" : "";
7: long long n = labs(numerator);
8: long long d = labs(denominator);
9: res += to_string(n / d);
10: long long r = n % d;
11: if (r == 0) return res;
12: res += ".";
13: r *= 10;
14: unordered_map<long long, int> rm;
15: while (r) {
16: if (rm.find(r) != rm.end()) {
17: res.insert(rm[r], 1, '(');
18: res += ")";
19: break;
20: }
21: rm[r] = res.size();
22: res += to_string(r / d);
23: r = (r % d) *10;
24: }
25: return res;
26: }
27: };
29. Divide Two Integers
Let's see what we should do if we want 3 to divide 18 where 18 is dividend and 3 is divisor.
(1) We subtract 3 from 18 and we get 15. 15 is larger than 3, so we shift 3 to the left by 1 bit and we get 6 which means we have 2 of 3s.
(2) We subtract 6 from 18 again and we get 12. 12 is larger than 6, so we shift 6 to the left by 1 bit again and we get 12 which means we have 4 of 3s.
(3) We subtract 12 from 18 and we get 6. Now 6 is less than 12, so we stop here and add the 4 to the result and subtract 12 from 18 as new dividend and start from 3 again as divisor. Now we go back to step (1) again. At the end, we'll get 2 so the final result is 4+2 = 6.
When implementing, we should be careful about overflow. Since -INT_MIN will be overflowed, so we can't simply flip the sign for dividend or divisor if they are negative, for example at line 6 and 7.
We should either assign dvd by casted long long dividend or do labs(dividend).
(1) We subtract 3 from 18 and we get 15. 15 is larger than 3, so we shift 3 to the left by 1 bit and we get 6 which means we have 2 of 3s.
(2) We subtract 6 from 18 again and we get 12. 12 is larger than 6, so we shift 6 to the left by 1 bit again and we get 12 which means we have 4 of 3s.
(3) We subtract 12 from 18 and we get 6. Now 6 is less than 12, so we stop here and add the 4 to the result and subtract 12 from 18 as new dividend and start from 3 again as divisor. Now we go back to step (1) again. At the end, we'll get 2 so the final result is 4+2 = 6.
When implementing, we should be careful about overflow. Since -INT_MIN will be overflowed, so we can't simply flip the sign for dividend or divisor if they are negative, for example at line 6 and 7.
We should either assign dvd by casted long long dividend or do labs(dividend).
1: class Solution { 2: public: 3: int divide(int dividend, int divisor) { 4: if (divisor == 0 || (dividend == INT_MIN && divisor == -1)) return INT_MAX; 5: int sign = ((dividend < 0) ^ (divisor < 0)) ? -1 : 1; 6:long long dvd = labs(dividend);7:long long dvs = labs(divisor);8: int res = 0; 9: while (dvd >= dvs) { 10: long long multiple = 1; 11: long long temp = dvs; 12: while (dvd >= (temp << 1)) { 13: multiple <<= 1; 14: temp <<= 1; 15: } 16: dvd -= temp; 17: res += multiple; 18: } 19: return sign == -1 ? -res : res; 20: } 21: };
Saturday, July 2, 2016
306. Additive Number
Let's observe the example first, "112358".
1st round, 1+1 = 2
2nd round, 1 + 2 = 3
3rd round, 2 + 3 = 5
4th round, 3 + 5 = 8
And let's observe the other example, "199100199"
1st round 1+ 9 = 10
2nd round 1+ 99 = 100
3rd round 99 + 100 = 199
What do you see? If there is an additive number in the substring, the additive number becomes the second number as input for next round. And we continue doing this until the following substring doesn't include the additive number or the following substring is right the additive number. Therefore, this can be done by recursion. Particularly, when calculating the sum, we should calculate by string instead of integer to avoid overflow.
1st round, 1+1 = 2
2nd round, 1 + 2 = 3
3rd round, 2 + 3 = 5
4th round, 3 + 5 = 8
And let's observe the other example, "199100199"
1st round 1+ 9 = 10
2nd round 1+ 99 = 100
3rd round 99 + 100 = 199
What do you see? If there is an additive number in the substring, the additive number becomes the second number as input for next round. And we continue doing this until the following substring doesn't include the additive number or the following substring is right the additive number. Therefore, this can be done by recursion. Particularly, when calculating the sum, we should calculate by string instead of integer to avoid overflow.
1: class Solution {
2: public:
3: bool isAdditiveNumber(string num) {
4: int n = num.size();
5: if (n < 3) return false;
6: for (int i = 1; i <= n/2; i++) {
7: for (int j = 1; j <= (n-i)/2; j++) {
8: if (validate(num.substr(0,i), num.substr(i,j), num.substr(i+j))) return true;
9: }
10: }
11: return false;
12: }
13: bool validate(string n1, string n2, string ns) {
14: if ((n1.size() > 1 && n1[0] == '0') || (n2.size() > 1 && n2[0] == '0')) return false;
15: string sum = add(n1, n2);
16: if (sum == ns) return true;
17: if (sum.size() > ns.size()) return false;
18: string ss = ns.substr(0, sum.size());
19: if (ss == sum) return validate(n2, sum, ns.substr(sum.size()));
20: else return false;
21: }
22: string add(string n1, string n2) {
23: int i = n1.size()-1, j = n2.size()-1, carry = 0;
24: string res;
25: while (i >= 0 && j >= 0) {
26: int sum = n1[i--]-'0' + n2[j--]-'0'+carry;
27: carry = sum / 10;
28: res.push_back(sum%10+'0');
29: }
30: while (i >= 0) {
31: int sum = n1[i--]-'0'+carry;
32: carry = sum / 10;
33: res.push_back(sum%10+'0');
34: }
35: while (j >= 0) {
36: int sum = n2[j--]-'0'+carry;
37: carry = sum / 10;
38: res.push_back(sum%10+'0');
39: }
40: if (carry) res.push_back(carry+'0');
41: reverse(res.begin(), res.end());
42: return res;
43: }
44: };
Subscribe to:
Posts (Atom)