Pythonで解説!回転ソート配列からのターゲット探索(重複要素対応)
昇順にソートされた配列が、事前に分からないあるピボット位置で回転されている状況を考えてみましょう。例えば、[0,0,1,2,2,5,6] という配列は、回転によって [2,5,6,0,0,1,2] のようになっている可能性があります。
この問題では、特定のターゲット値が配列内に存在するかどうかを判定します。ターゲットが見つかれば true を、存在しなければ false を返します。例えば、配列が [2,5,6,0,0,1,2] でターゲットが 0 の場合、出力は True となります。
この問題は通常の二分探索とは異なり、重複した要素が含まれる 点が特徴です。重複があると、どちら側がソート済みなのか判別できないケースが発生するため、その場合には探索範囲を少しずつ狭めていく工夫が必要になります。
アルゴリズムの手順
lowを 0、highを配列のサイズで初期化しますlow < highの間、以下を繰り返しますmid := low + (high - low) / 2を計算しますnums[mid]がターゲットと一致すれば true を返しますnums[low] == nums[mid]かつnums[high - 1] == nums[mid]の場合(両端の中間値との一致により判断不能):lowを 1 増やし、highを 1 減らして、次の反復へ進みます
nums[low] <= nums[mid]の場合(左半分がソート済み):target >= nums[low]かつtarget < nums[mid]ならばhigh := mid、そうでなければlow := mid + 1
- それ以外の場合(右半分がソート済み):
target <= nums[high - 1]かつtarget > nums[mid]ならばlow := mid + 1、そうでなければhigh := mid
- ループを抜けても見つからなかった場合は false を返します
それでは、以下の実装例を見て理解を深めましょう。
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 True
if nums[low] == nums[mid] and nums[high-1] == nums[mid]:
low +=1
high -=1
continue
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 False
ob1 = Solution()
print(ob1.search([2,5,6,0,0,1,2], 0))
入力
[2,5,6,0,0,1,2] 0
出力
True
計算量について
要素がすべてユニークな場合は通常の二分探索と同様に O(log n) で動作しますが、重複要素が多いケースでは探索範囲を狭める処理が必要になるため、最悪計算量は O(n) になる点に注意してください。
-
Pythonで挿入ソート(Insertion Sort)を実装する方法:アルゴリズムとサンプルコードを徹底解説
この記事では、Python 3.x(およびそれ以前のバージョン)における挿入ソートの実装方法について詳しく解説します。挿入ソートは、トランプの手札を整理するイメージに近い、直感的で理解しやすいソートアルゴリズムです。挿入ソートのアルゴリズム挿入ソートは以下の手順で動作します。入力要素を順番に走査し、各反復ごとにソート済みの配列部分を少しずつ拡張していきます。現在注目している要素(キー)を、ソート済み部分の中で最も大きい値と比較します。キーがその値より大きければ、要素は元の位置のまま次の要素へ進みます。そうでなければ、ソート済み配列内の正しい位置を探し出し、そこへ移動させます。具体的には、ソート
-
Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法
この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要