Pythonで配列が「ソート済み+回転」状態かどうかを判定するプログラム
問題の概要
nums という配列が与えられたとき、その配列が「もともと非減少順(昇順)にソートされていたものを、何度か(0回でも可)回転させた結果」になっているかどうかを判定します。配列には重複した要素が含まれている場合もあります。
たとえば、入力が nums = [12,15,2,5,6,9] の場合、出力は True になります。これは、ソート済みの配列 [2,5,6,9,12,15] を右に2回転させると [12,15,2,5,6,9] になるためです。
解決のアプローチ
この問題は、次の手順で解くことができます。
- 変数 j を 0 に初期化します。
- j が「配列の長さ − 1」未満であり、かつ nums[j] ≤ nums[j+1] が成り立っている間、j を 1 ずつ増やします。これにより、昇順が崩れる位置(境界)を見つけます。
- res を、「インデックス j+1 以降の部分配列」と「先頭からインデックス j までの部分配列」を連結したものとして作成します。これで回転前の状態に戻した配列が得られます。
- i を 0 から res の長さ − 2 まで動かしながら確認し、res[i] > res[i+1] となる箇所があれば False を返します。
- 最後まで昇順が崩れなければ、True を返します。
Pythonでの実装例
理解を深めるために、以下の実装例を見てみましょう。
def solve(nums):
j = 0
while (j < len(nums) - 1 and nums[j] <= nums[j + 1]):
j += 1
res = nums[j + 1 : len(nums)] + nums[0:j + 1]
for i in range(len(res) - 1):
if res[i] > res[i + 1]:
return False
return True
nums = [12,15,2,5,6,9]
print(solve(nums))入力
[12,15,2,5,6,9]
出力
True
アルゴリズムのポイント
このアルゴリズムでは、まず昇順が崩れる最初の位置を特定し、そこで配列を分割して連結し直すことで「回転を解除」します。そのうえで全体が再び昇順になっていれば、元の配列は「ソート済み+回転」だったことになります。
計算量は O(n)、追加で必要なメモリも O(n)(連結用の新しい配列 res を作成するため)です。重複要素があっても比較条件に「≤」を使っているため、正しく判定できる点も特徴です。
-
Pythonで挿入ソート(Insertion Sort)を実装する方法:アルゴリズムとサンプルコードを徹底解説
この記事では、Python 3.x(およびそれ以前のバージョン)における挿入ソートの実装方法について詳しく解説します。挿入ソートは、トランプの手札を整理するイメージに近い、直感的で理解しやすいソートアルゴリズムです。挿入ソートのアルゴリズム挿入ソートは以下の手順で動作します。入力要素を順番に走査し、各反復ごとにソート済みの配列部分を少しずつ拡張していきます。現在注目している要素(キー)を、ソート済み部分の中で最も大きい値と比較します。キーがその値より大きければ、要素は元の位置のまま次の要素へ進みます。そうでなければ、ソート済み配列内の正しい位置を探し出し、そこへ移動させます。具体的には、ソート
-
Pythonで学ぶ挿入ソート(Insertion Sort)の仕組みと実装方法
この記事では、Python 3.xにおける挿入ソート(Insertion Sort)の基本的な考え方と、実際のコードによる実装方法をわかりやすく解説します。 挿入ソートのアルゴリズム 挿入ソートは、配列を「整列済みの部分」と「未整列の部分」に分け、未整列の要素を一つずつ取り出して、整列済み部分の正しい位置に挿入していくシンプルなソート手法です。処理の手順は以下の通りです。 1. 各反復ごとに整列済みの配列を少しずつ拡大しながら、入力要素を走査する。 2. 現在の要素(キー)を、整列済み配列内の最大値と比較する。 3. キーがその最大値より大きければ、要素はそのままの位置に置かれ、 次の要