Pythonで平方根の整数部分を求める方法|組み込み関数を使わない二分探索アルゴリズム
はじめに
本記事では、非負整数 n が与えられたとき、r * r = n を満たす数 r を求め、その結果を最も近い整数へ切り捨てる方法を解説します。重要なポイントは、組み込みの平方根関数(math.sqrt など)を使用せずに実装するという点です。
例えば、入力が 1025 の場合、出力は 32 となります。これは 32 × 32 = 1024 ≤ 1025 であり、33 × 33 = 1089 > 1025 だからです。
解法のアプローチ:二分探索
この問題は「二分探索(バイナリサーチ)」を使うことで効率的に解けます。探索範囲を半分ずつ絞り込んでいくことで、計算量は O(log n) に抑えられます。
アルゴリズムの手順
n <= 1の場合は、そのままnを返します(0 と 1 の平方根はそれぞれ 0 と 1 になるため)。- 探索範囲の下限
start := 1、上限end := nを設定します。 start < endの間、以下を繰り返します。- 中央値
mid := start + end / 2を計算します。 mid * mid <= nであれば、start := mid + 1とし、より大きい候補を探します。- そうでなければ、
end := midとし、探索範囲を狭めます。
- 中央値
- 最後に
start - 1を返します。これが切り捨てられた平方根です。
実装例
以下に Python での具体的な実装を示します。
class Solution:
def solve(self, n):
if n <= 1:
return n
start, end = 1, n
while start < end:
mid = start + end >> 1
if mid * mid <= n:
start = mid + 1
else:
end = mid
return start - 1
ob = Solution()
print(ob.solve(1025))
入力
1025
出力
32
コードのポイント
start + end >> 1はビットシフト演算を使った整数除算で、(start + end) // 2と同じ意味です。高速に中央値を求められます。- ループ終了時の
startは「条件を満たさない最初の値」を指しているため、-1することで答えが得られます。 - 大きな数に対しても O(log n) の時間で処理できるため、ニュートン法などと並んで効率的な手法の一つです。
まとめ
組み込みの平方根関数を使わずに整数の平方根を求めるには、二分探索が有効です。探索範囲を繰り返し半分に絞り込むことで、正確かつ高速に切り捨てた平方根を計算できます。競技プログラミングや面接対策としても頻出のテクニックなので、ぜひマスターしておきましょう。
-
Pythonで二分木を反転する方法:再帰を使った実装を解説
二分木の反転とは二分木が与えられたとき、その左右の子ノードを入れ替えて「鏡像」のような木を作ることを二分木の反転(Invert Binary Tree)と呼びます。これはアルゴリズムの学習やコーディング面接でも頻出のトピックです。例えば、次のような二分木があったとします。これを反転すると、すべてのノードの左部分木と右部分木が入れ替わり、以下のような木になります。解き方:再帰的アプローチこの問題は再帰を使うと非常にシンプルに解けます。考え方は以下の3ステップです。ルートが None(null)であれば、そのまま返す(ベースケース)現在のノードの左ポインタと右ポインタを入れ替える左部分木と右部分木
-
Pythonで二分木のパス合計(Path Sum)を判定する方法
パス合計問題とは二分木と目標の合計値が与えられたとき、根から葉までの経路をたどった際のノード値の合計が、与えられた値と一致するような経路が存在するかどうかを判定します。例として、木が [0, -3, 9, -10, null, 5] という構成で、合計値が 14 の場合を考えてみましょう。このとき、0 → 9 → 5 という経路が存在し、その合計はちょうど 14 になるため、答えは True となります。解法のアプローチこの問題は再帰を使うことで簡潔に解くことができます。手順は以下の通りです。根ノードが null(空)の場合、False を返します。左右の子ノードが両方とも空(つまり葉ノード)