45. Pow(x, n)
読了目安 約1分
Recursion / LeetCode 50 (Medium) — x の n 乗を繰り返し二乗法で O(log n) で計算する。
この章の目次
問題
LeetCode 50. Pow(x, n)(Medium / カテゴリ: Recursion)
実数 x と整数 n が与えられ、x の n 乗を計算します。
n は負にもなります。
x を n 回掛ける O(n) では遅く、O(log n) が求められます。
考え方
ヒント 1
x^10 = (x^5)^2 のように、指数を半分にした結果を 2 乗すれば計算回数を大きく減らせます。 繰り返し二乗法と呼ばれる手法です。
ヒント 2
指数が奇数のときは x^(2k+1) = (x^k)^2 × x と、余った 1 個分を掛けます。
基底は x^0 = 1 です。
n が負なら x を 1/x に置き換え、指数は絶対値で扱います。
Swift 実装のポイント
n == Int.minのとき-nはオーバーフローで実行時エラーになります。絶対値はn.magnitude(UIntを返す)で取ると安全です。- Double は誤差が出るので
==で比較しません。テストコードはabs(a - b) < 1e-9で判定しています。 - 再帰の深さは指数のビット数(最大 64 程度)なので、スタックあふれの心配はありません。
模範解答
class Solution {
func myPow(_ x: Double, _ n: Int) -> Double {
let base = n < 0 ? 1 / x : x
return power(base, n.magnitude)
}
private func power(_ x: Double, _ m: UInt) -> Double {
if m == 0 { return 1 }
let half = power(x, m / 2)
return m % 2 == 0 ? half * half : half * half * x
}
}計算量: O(log n)。