Pow(x, n)

Difficulty: Medium

Implement a function that raises a number x to an integer power n - that is, computes x^n - without relying on a built-in power function.

n can be negative, in which case x^n means 1 / x^(-n).

Examples

Input: x = 2.0, n = 10
Output: 1024.0

2 multiplied by itself 10 times.

Input: x = 2.1, n = 3
Output: 9.261

2.1 * 2.1 * 2.1 = 9.261.

Input: x = 2.0, n = -2
Output: 0.25

x^-2 means 1 / x^2 = 1 / 4 = 0.25.

Constraints

  • -100 < x < 100

  • -2^31 <= n <= 2^31 - 1

  • x != 0, or n > 0

  • n can be negative

Approach

The most direct approach multiplies x by itself n times in a loop. It's easy to reason about, but it does n multiplications, which is noticeably slow once n is large (say, in the billions).

A much faster approach notices that you don't need to redo all the multiplications for each power - if you already know x raised to n/2, you can square that single result to get x raised to n (adjusting by one extra factor of x when n is odd). Repeating that halving idea, the exponent shrinks by half at every step instead of by just one, cutting the number of multiplications down to roughly log2(n). A negative n is handled up front, by computing with 1/x and a positive exponent instead.

Solutions

Brute Force - Repeated Multiplication

For a negative exponent, first flip x to 1/x and make n positive. Then multiply x into a running result, once for every unit of n.

function myPow(x, n) {
  if (n < 0) {
    x = 1 / x;
    n = -n;
  }

  let result = 1;
  for (let i = 0; i < n; i++) {
    result *= x;
  }

  return result;
}

Time: O(n) · Space: O(1)

Optimal - Fast (Binary) Exponentiation

For a negative exponent, first flip x to 1/x and make n positive, same as before. Then compute the power recursively: find x^(n/2), square it, and multiply in one extra factor of x if n was odd. Each recursive call halves the exponent, instead of only reducing it by one.

function myPow(x, n) {
  if (n < 0) {
    x = 1 / x;
    n = -n;
  }

  return fastPow(x, n);
}

function fastPow(x, n) {
  if (n === 0) return 1;

  const half = fastPow(x, Math.floor(n / 2));
  const halfSquared = half * half;

  return n % 2 === 0 ? halfSquared : halfSquared * x;
}

Time: O(log n) · Space: O(log n), for the recursion stack