Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonでサブ配列を1回反転するだけで配列がソートされるかどうかを判定する方法

すべての要素がユニーク(重複なし)である配列 nums があるとします。この配列の部分配列(サブ配列)を1つだけ反転したとき、配列全体がソートされた状態になるかどうかを判定するのが本記事のテーマです。なお、配列がすでにソート済みの場合も True を返します。

たとえば、入力が nums = [4,6,27,25,15,9,37,42] の場合を考えてみましょう。[27,25,15,9] の部分を反転すると [4,6,9,15,25,27,37,42] となり、配列全体が昇順に整列します。したがって、この場合の出力は True になります。

アルゴリズムのアプローチ

この問題は、配列を一度走査するだけで線形時間 O(n) で判定できます。手順は以下の通りです。

  • n を配列 nums のサイズとします。
  • 要素が1つしかない場合は、すでにソートされているとみなし True を返します。
  • i := 1 として、昇順が続いている限りインデックスを進めます。
  • nums[i-1] < nums[i] が成り立つ間は昇順なので i を進め、初めて崩れた位置でループを抜けます。
  • j := i から始め、j < n かつ nums[j] < nums[j-1] の間(=降順になっている区間)、j を進めて反転候補の範囲を特定します。
  • 反転候補の先頭要素が、直前の昇順区間の末尾より小さい場合は、反転しても整合しないため False を返します。
  • j == n に達していれば、末尾まで反転で収まるため True を返します。
  • 残りの区間についても k := j 以降が昇順に保たれているかを確認し、崩れていれば False、最後まで問題なければ True を返します。

実装例(Pythonコード)

def solve(nums):
    n = len(nums)
    if n == 1:
        return True

    i = 1
    for i in range(1, n):
        if nums[i - 1] < nums[i]:
            if i == n:
                return True
        else:
            break

    j = i
    while j < n and nums[j] < nums[j - 1]:
        if i > 1 and nums[j] < nums[i - 2]:
            return False
        j += 1

    if j == n:
        return True

    k = j
    if nums[k] < nums[i - 1]:
        return False

    while k > 1 and k < n:
        if nums[k] < nums[k - 1]:
            return False
        k += 1
    return True

nums = [4,6,27,25,15,9,37,42]
print(solve(nums))

入力

[4,6,27,25,15,9,37,42]

出力

True

計算量の評価

このアルゴリズムは配列を高々数回走査するだけで完了するため、時間計算量は O(n) です。また、追加のデータ構造を使用しないため、空間計算量は O(1) となります。配列全体を実際に反転・コピーして比較する方法(O(n) の追加メモリが必要)よりも効率的で、大きな入力にも対応できます。

まとめ

「1つのサブ配列を反転するだけでソートできるか」という問題は、昇順→降順→昇順というパターンを線形走査で検出することで解決できます。境界条件(すでにソート済み、要素数1、反転区間が配列の端に接しているケースなど)を丁寧に扱うことが、正確な実装のポイントです。

  1. Pythonでソート済み配列内の数値が過半数要素(マジョリティ要素)かどうかを判定する方法

    問題概要 非降順(昇順)にソートされた整数配列 nums と、ある数値 target が与えられます。この target が「過半数要素(マジョリティ要素)」であるかどうかを判定してください。ここで、長さ N の配列における過半数要素とは、配列内に N/2 回より多く出現する要素のことを指します。 例えば、配列が [2,4,5,5,5,5,5,6,6] で target が 5 の場合を考えてみましょう。配列の長さは 9 なので、9/2 = 4.5 より多く出現すれば過半数要素です。実際、5 は 5 回出現しているため条件を満たし、出力は true になります。 解法のアプローチ:二分探索の

  2. Pythonで配列が単調(モノトニック)かどうかを判定する方法

    この記事では、与えられた配列が「単調(モノトニック)」であるかどうかを判定するための考え方と実装方法について解説します。 問題の定義 n個の整数を含む配列 Arr が入力として与えられます。このとき、その配列が単調な性質を持っているかどうかを判定する必要があります。 配列が単調であるとは、要素が最初から最後まで連続して増加しているか、または連続して減少している状態を指します。つまり、増加と減少が混在していない配列が単調な配列です。 数学的な定義 配列 A が単調増加であるのは、すべての i <= j に対して次の条件が成り立つ場合です。 A[i] <= A[j] 同様に、配列 A