The O(n) Club: Exponentiation by Squaring in Java – Because Your CPU Has Feelings Too
⚡ TL;DR
If you’re still looping through n multiplications to do
x^n
, I hope you brought extra coffee. Exponentiation by squaring gives you O(log n) power in just a few lines. Here’s prehistory:// Brute force cave-dweller edition public double powNaive(double x, int n) { double result = 1.0; int absN = Math.abs(n); for (int i = 0; i < absN; i++) { result *= x; } return n < 0 ? 1.0 / result : result; }
🧠 How Devs Usually Mess This Up
Let’s be honest. Most folks nail the “multiply x by itself n times” routine and call it a day. Throw a big n at it and—surprise!—it’s slower than an underfunded government project. Oh, and negative exponents? Classic “I’ll handle that later” energy… right up until the interviewer asks, “But what if n is -2147483648?” You blink. The stack trace blinks back. And if x is 0 and n is negative, congratulations, you now have a philosophical discussion about dividing by zero. Most rookie solutions miss:
- Negative exponents (x-n = 1/xn – math isn’t just for optimists)
- Zero to a negative power – which isn’t math, it’s a trap
n == Integer.MIN_VALUE
– because Math.abs(-2,147,483,648) actually isn’t an int (yes, it overflows; yes, Java will giggle and then break things)
🔍 What’s Actually Going On
Picture n not as millions of multiplications, but as a series of binary switches—on or off, leapfrogging you through the argument like a caffeinated bunny. Every bit in n’s binary form says “multiply or don’t,” and rather than walking, you take squaring shortcuts. If n’s even, square the base and halve n. If odd, tack a multiplication onto your result, then proceed. Could you do this recursively? Sure. Should you, when the iterative is safer and easier to debug at 11:59pm? Not unless you enjoy seeing StackOverflowError more than your friends.
🛠️ PseudoCode
- If n == 0: Return 1. Even 00. (Math police will let it slide for this problem.)
- If n < 0: Set a flag (neg = true), make N = abs(n), you’ll invert at the end
- Use a long for N to keep
Integer.MIN_VALUE
from sabotaging your interview - Set result = 1.0
- While N > 0:
- If N is odd: result *= x
- Square x: x *= x
- Halve N: N >>= 1
- If neg: return 1/result; else, return result
💻 The Code
// Welcome to O(log n) club!
public double myPow(double x, int n) {
if (n == 0) return 1.0;
long N = n; // Use long to dodge Integer.MIN_VALUE overflow
boolean neg = N < 0;
N = Math.abs(N);
double result = 1.0;
while (N > 0) {
if ((N & 1) == 1) {
result *= x;
}
x *= x;
N >>= 1;
}
return neg ? 1.0 / result : result;
}
⚠️ Pitfalls, Traps & Runtime Smacks
- n == Integer.MIN_VALUE: Calculate abs(n) in a long to prevent numeric midlife crises
- x == 0 && n < 0: That’s not a power, that’s a bug. Avoid division by zero, unless you really like seeing NaN
- Floating-point errors: Java’s
double
isn’t magic. Rounding errors pop up with huge exponents or lots of decimal places. Close enough for most interviews, but warn your quant friends - Recursion fans beware: n can be mega large; use an iterative loop unless you like causing your machine existential dread
- Time/Space: All done in O(log n) time, O(1) space. Even your JVM’s garbage collector’ll high five you
🧠 Interviewer Brain-Tattoo
“Exponentiation by squaring: because why climb 2 billion stairs when you could just take the elevator with a jetpack?”