Pythonで配列が「ソート済みかつ回転」しているかを判定する方法
問題の概要
n個の一意な値で構成される配列があるとします。この配列が「昇順にソートされた状態から回転した配列」であるかどうかを判定してください。ただし、少なくとも1回の回転が必要なため、完全にソートされただけの配列は「ソートかつ回転」とはみなされません。
たとえば、入力が nums = [4,5,6,8,1,3] の場合、出力は True になります。この配列を2回回転すると [1, 3, 4, 5, 6, 8] という昇順の配列になるためです。
アルゴリズムの考え方
回転されたソート配列の最大の特徴は、最小値を境に配列が2つの昇順部分に分かれることです。この性質を利用して、以下の手順で判定を行います。
- 配列内の最小値
min_elementと、そのインデックスmin_indexを求めます。 - フラグ
before_sortedをTrueで初期化し、先頭からmin_indexの直前までの要素が昇順になっているかを確認します。降順の箇所が見つかればFalseにしてループを抜けます。 - 同様に、フラグ
after_sortedをTrueで初期化し、min_index + 1から末尾までの要素が昇順になっているかを確認します。 before_sortedとafter_sortedがどちらもTrueであり、かつ配列の最後の要素が先頭の要素より小さい(nums[-1] < nums[0])場合にTrueを返します。それ以外はFalseを返します。
最後の条件 nums[-1] < nums[0] が重要なポイントです。この条件により、単にソートされただけで回転が行われていない配列を正しく除外できます。
実装例(Python)
def solve(nums):
min_element = min(nums)
min_index = nums.index(min_element)
# 最小値より前の部分が昇順かどうかを確認
before_sorted = True
for i in range(1, min_index):
if nums[i] < nums[i - 1]:
before_sorted = False
break
# 最小値より後の部分が昇順かどうかを確認
after_sorted = True
for i in range(min_index + 1, len(nums)):
if nums[i] < nums[i - 1]:
after_sorted = False
break
# 両方の条件と回転の条件を満たすか判定
if before_sorted and after_sorted and nums[-1] < nums[0]:
return True
else:
return False
nums = [4, 5, 6, 8, 1, 3]
print(solve(nums))
入力
[4, 5, 6, 8, 1, 3]
出力
True
計算量について
このアルゴリズムは配列を最大2回走査するため、時間計算量は O(n) です。また、追加のデータ構造を使用しないため、空間計算量は O(1) で抑えられます。
まとめ
配列が「ソート済みかつ回転」しているかの判定は、最小値の位置を基準に前後の部分配列がそれぞれ昇順になっているか、そして配列の端同士の大小関係を確認することで効率的に行えます。一意な値を持つ配列を前提とすれば、O(n) の線形時間で確実に判定できるシンプルで実用的な手法です。
-
Pythonでリストがソート済みかどうかを確認する2つの方法
Pythonにおいて、リストは最も広く使われているデータコレクションの一つです。開発の現場では、与えられたリストがすでに昇順にソートされているかどうかを確認したい場面によく出会います。この記事では、その判定を行うための代表的なアプローチを2つ、サンプルコード付きで紹介します。 方法1:sort()メソッドを使う まず元のリストのコピーを作成し、そのコピーに対してsort()メソッドを適用します。その後、ソート済みのコピーと元のリストを比較し、両者が完全に一致していれば「元のリストはすでにソートされている」と判断できます。 サンプルコード listA = [11,23,42,51,67] # 与
-
Pythonのソート徹底解説:sorted()、list.sort()、np.argsort()、np.lexsort()の違いと使い方
データ要素を特定の順序で並べ替える処理は、プログラミングにおいて非常によく使われる操作です。Pythonでは配列(リスト)の要素をソートするために、sorted()関数とlist.sort()メソッドという2つの方法が用意されています。さらに、より高度なソートが必要な場合はNumPyライブラリのargsort()やlexsort()が活躍します。本記事では、それぞれの使い方と動作の違いを具体例とともにわかりやすく解説します。sorted():元の配列を変更せずにソートsorted()関数は、元の配列を変更することなく、ソート済みの新しい配列を返します。a = [9,5,3,1,12,6] b