Realize pow(x, n), that is, calculate the N-power function of X (i.e., xn). Library functions should not be used and large numbers should not be considered.
Example 1:
Input: x = 2.00000, n = 10
Output: 1024.00000
Example 2:
Input: x = 2.10000, n = 3
Output: 9.26100
Example 3:
Input: x = 2.00000, n = -2
Output: 0.25000
Explanation: 2-2 = 1 / 22 = 1 / 4 = 0.25
Tips:
-100.0 < x < 100.0 -231 <= n <= 231-1 -104 <= xn <= 104
Source: LeetCode
Link: https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof
The copyright belongs to Lingkou network. For commercial reprint, please contact the official authorization, and for non-commercial reprint, please indicate the source.
The topic is very simple, but this topic needs to fully consider the boundary and special situations, such as the case where x is negative and n is negative. These situations need to be taken into account.
If these situations are taken into account, it is easy to write down the following solutions:
class Solution { public: double myPow(double x, int n) { bool flage = (n >= 0) ? true : false; double res = 1; if(x == 0) return 0; if(x == 1) return 1; int abs_n = flage ? n : -n; //int falge_res = ( abs_n%2 == 0) ? 1 :( x >= 0) ? 1 : -1; if(flage){ while(abs_n--){ res = res*x; } } else{ while(abs_n--) res = res*(1/x); } return res;//*falge_res ; } };
But there is a special test case that can't pass:
2.00000 -2147483648
Why can't this test case pass?
Because the value is stored in the computer with complement, people with a little computer foundation will know, int32_ The range of positive and negative numbers of T is inconsistent. Therefore, you can use long variables to get n first, and then reverse long numbers to avoid overflow.
long b = n; ..... int abs_n = flage ? b: -b;
At this time, the submission is found to have timed out, because the complexity at this time is O(n). The larger the index, the longer the time-consuming. It seems that the problem requires us to reduce the complexity.
Then we remember the dichotomy,
a^n = a^(n/2)*a^(n/2) n Even number a^n = a^((n-1)/2)*a^((n-1)/2)*a n Odd number
In this way, the complexity is reduced to O(log n).
It should be noted that if n is an even number, the division can be operated with displacement. Similarly, if n is an odd number, (n-1) > > 1 = = n > > 1, so the operation with displacement can not be reduced by one
The idea of recursion is relatively simple,
Explain two points,
1: In order to simplify the judgment, simply make a judgment at the function entry and uniformly process the data into positive numbers
2: Here, recursive functions are proposed separately for easy understanding
As follows:
class Solution { public: double kernel(double x, long n){ if( n == 0) return 1; if( n == 1) return x; double res = kernel(x,n>>1); res = res*res; if((n & 0x1) == 1) res = res*x; return res; } double myPow(double x, int n) { long b = n; bool flage = (b >= 0) ? true : false; double res = 1.0; if(x == 0) return 0; if(x == 1) return 1; long abs_n = flage ? b : -b; if(!flage){ x = 1/x; abs_n = -b; } res = kernel(x,abs_n); return res; } };
Recursion is easy to understand, but each recursive call of the program will incur some overhead. Therefore, iterative methods are also provided here for reference.
class Solution { public: double myPow(double x, int n) { long b = n; bool flage = (b >= 0) ? true : false; double res = 1.0; if(x == 0) return 0; if(x == 1) return 1; long abs_n = flage ? b : -b; if(!flage){ x = 1/x; abs_n = -b; } while(abs_n > 0){ if( (abs_n&1) == 1) res*=x; x = x*x; abs_n = abs_n >> 1; } return res; } };
Like the previous steps, two points need to be explained,
1: N > > 1 must be assigned to N. direct n > > 1 has no side effects, and the value of n will not change
2: Here, when n is an even number, x=x*x, which is not assigned to res, will it not lead to omission? The answer is no, because even number divided by 2 must be odd, so the value of res is in ABS_ Update to when n = 1.
We can write recursive code first, and then change it to iterative form.