RECURSION & BACKTRACKING › RECURSION PROBLEMS
Open — the attempt gate is not wired up yet
This editorial is meant to unlock after you have run the problem at least once, with the worked solution behind one further deliberate click. That needs per-learner unlock state nothing stores today, so for now the whole article is open.
Try it yourself first →The direct definition of x^n multiplies x by itself n times, but that repeats work unnecessarily. For example, x^8 can be formed as x, then x^2, then x^4, then x^8 by squaring each result. Every squaring doubles the exponent represented by the current base, so the useful powers grow exponentially while the number of steps grows logarithmically.
Write the exponent as a sum of powers of two. For n = 13, the binary form is 1101, so x^13 is x^8 multiplied by x^4 multiplied by x. The loop keeps a current power in x, multiplies it into the answer when the current exponent bit is 1, then squares that power and shifts the exponent right to inspect the next bit.
A negative exponent changes the value to a reciprocal: x^(-n) = (1/x)^n. Convert x to 1/x before the loop, but do not negate the original int directly. The smallest int cannot represent its own positive counterpart, so the exponent must first be widened to long long and only then negated.
| MEASURE | BOUND | WHY |
|---|---|---|
| Time | O(log(|n| + 1)) | Each iteration removes one binary digit by shifting N right, so there are at most logarithmically many iterations. Each iteration performs only constant-time bit checks, at most one answer multiplication, and one squaring; the worst allowed exponents therefore take about 31 or 32 iterations. |
| Space | O(1) | The algorithm stores only the widened exponent, the current base, and the accumulated answer. The returned double is required output and is excluded from extra space, and the working memory stays constant even for the largest or most awkward exponent. |
#include <cmath>
using namespace std;
class Solution {
public:
double myPow(double x, int n) {
long long N = n;
if (N < 0) {
x = 1 / x;
N = -N;
}
double ans = 1.0;
while (N > 0) {
if (N & 1) {
ans *= x;
}
x *= x;
N >>= 1;
}
return ans;
}
};The order inside the loop is deliberate. The current x represents the power for the bit being inspected, so ans must use it before x is squared. After that contribution is recorded, squaring prepares x for the next bit. The long long conversion is equally important: when n is -2^31, the positive magnitude is 2^31, which an int cannot hold.
A recursive solution can apply the identity x^n = (x^(n/2))^2 for even n, and x^n = x times x^(n-1) for odd n. It is a different arrangement of the same optimization, not a faster algorithm. It makes the mathematical structure compact, but it uses O(log(|n| + 1)) call-stack space instead of the iterative version's O(1), so the loop is the safer default.
#include <cmath>
using namespace std;
class Solution {
public:
double myPow(double x, int n) {
long long N = n;
if (N < 0) {
x = 1 / x;
N = -N;
}
return power(x, N);
}
private:
double power(double x, long long n) {
if (n == 0) {
return 1.0;
}
double half = power(x, n / 2);
double result = half * half;
if (n & 1) {
result *= x;
}
return result;
}
};