Pythonで回転ソート済み配列からターゲットを検索する方法を解説
昇順にソートされた配列が、事前に知らされていないあるピボット(軸)を基準に回転されている状況を考えてみましょう。例えば、[0,1,2,4,5,6,7] という配列は、回転によって [4,5,6,7,0,1,2] のようになります。ここでの課題は、指定されたターゲット値をこの配列の中から探し出すことです。ターゲットが配列内に存在すればそのインデックスを返し、存在しなければ -1 を返します。なお、配列には重複した要素は含まれていないものとします。
例えば、配列が [4,5,6,7,8,0,1,2] でターゲットが 0 の場合、0 はインデックス 5 の位置に存在するため、出力は 5 となります。
解法のアプローチ
この問題は、通常の二分探索を応用することで O(log n) の時間計算量で効率的に解けます。ポイントは、回転ソート済み配列をどの位置で分割しても、必ず少なくとも片側の半分は正しくソートされているという性質です。この性質を利用して、ターゲットが存在しうる範囲を半分ずつ絞り込んでいきます。
具体的な手順は以下の通りです。
- low := 0、high := 配列の長さ と初期化する
- low < high の間、以下を繰り返す
- mid := low + (high - low) / 2 として中央の位置を求める
- arr[mid] == target であれば mid を返す
- arr[low] <= arr[mid] の場合(左半分がソート済みの場合)
- target >= arr[low] かつ target < arr[mid] であれば high := mid、そうでなければ low := mid + 1
- それ以外の場合(右半分がソート済みの場合)
- target <= arr[high - 1] かつ target > arr[mid] であれば low := mid + 1、そうでなければ high := mid
- ループを抜けても見つからなければ -1 を返す
Pythonでの実装例
理解を深めるために、以下の実装例を見てみましょう。
class Solution(object): def search(self, nums, target): low = 0 high = len(nums) while low<high: mid = low + (high-low)//2 if nums[mid] == target: return mid if nums[low]<=nums[mid]: if target >=nums[low] and target <nums[mid]: high = mid else: low = mid+1 else: if target<=nums[high-1] and target>nums[mid]: low = mid+1 else: high = mid return -1 ob1 = Solution() print(ob1.search([4,5,6,7,8,0,1,2], 0))
入力
[4,5,6,7,8,0,1,2] 0
出力
5
このコードでは、まず中央の要素とターゲットを比較し、一致していれば即座にインデックスを返します。一致しない場合は、左半分と右半分のどちらが正しくソートされているかを判定し、ターゲットがソート済み側の範囲に収まるかどうかで探索範囲を更新します。これにより、配列が回転していても線形探索ではなく対数時間での検索が可能になります。
-
Pythonで挿入ソート(Insertion Sort)を実装する方法:アルゴリズムとサンプルコードを徹底解説
この記事では、Python 3.x(およびそれ以前のバージョン)における挿入ソートの実装方法について詳しく解説します。挿入ソートは、トランプの手札を整理するイメージに近い、直感的で理解しやすいソートアルゴリズムです。挿入ソートのアルゴリズム挿入ソートは以下の手順で動作します。入力要素を順番に走査し、各反復ごとにソート済みの配列部分を少しずつ拡張していきます。現在注目している要素(キー)を、ソート済み部分の中で最も大きい値と比較します。キーがその値より大きければ、要素は元の位置のまま次の要素へ進みます。そうでなければ、ソート済み配列内の正しい位置を探し出し、そこへ移動させます。具体的には、ソート
-
Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法
この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要