Pythonで回転操作により配列をソートできるか判定する方法
問題の概要
数値のリスト nums が与えられ、「回転」操作を使ってこのリストを昇順にソートできるかどうかを判定します。ここでいう回転とは、配列の末尾から連続するいくつかの要素を取り出し、そのまま配列の先頭へ移動させる操作のことです。
例えば、入力が nums = [4,5,6,1,2,3] の場合を考えてみましょう。末尾の3つの要素「1, 2, 3」を先頭に移動させると [1,2,3,4,5,6] となり、ソートが完了します。したがって、この場合の出力は True となります。
解法のアプローチ
この問題は、次の手順で解くことができます。
nをリストnumsのサイズとします。- もし
numsがすでにソート済みであれば、Trueを返します。 - そうでない場合は、以下の処理を行います。
statusをTrueで初期化します。iを 0 から n-2 まで走査し、nums[i] > nums[i + 1]となる最初の位置(降順になっている箇所)でループを抜けます。iに 1 を加算します。kを i から n-2 まで走査し、再びnums[k] > nums[k + 1]となる箇所が見つかったら、statusをFalseにしてループを抜けます。statusがFalseの場合はFalseを返します。- そうでなければ、
nums[n - 1] <= nums[0]が成り立てばTrueを、成り立たなければFalseを返します。
なぜこの方法で判定できるのか
回転によってソート可能な配列は、必ず「2つの昇順の区間」に分割できます。つまり、配列内で降順になっている箇所(nums[i] > nums[i+1])は最大でも1箇所しか存在せず、その境界を境に前半部分・後半部分がそれぞれ昇順になっていなければなりません。
さらに、後半部分の最後の要素が前半部分の先頭の要素以下(nums[n-1] <= nums[0])であれば、境界をまたいでも昇順が保たれるため、適切な位置で回転することで完全にソートされた配列を得ることができます。
実装例
理解を深めるために、以下の実装を見てみましょう。
def solve(nums):
n = len(nums)
if all(nums[i] <= nums[i + 1] for i in range(len(nums) - 1)):
return True
else:
status = True
for i in range(n - 1):
if nums[i] > nums[i + 1]:
break
i += 1
for k in range(i, n - 1):
if nums[k] > nums[k + 1]:
status = False
break
if not status:
return False
else:
if nums[n - 1] <= nums[0]:
return True
return False
nums = [4,5,6,1,2,3]
print(solve(nums))
入力
[4,5,6,1,2,3]
出力
True
計算量について
このアルゴリズムの時間計算量は O(n)、空間計算量は O(1) です。配列を最大2回走査するだけで判定が完了するため、非常に効率的な手法と言えます。
-
Pythonで隣接要素の条件付きスワップにより配列をソートできるか判定する方法
問題の概要0からn-1までの範囲に含まれる要素で構成された、順序がバラバラの数値配列numsがあるとします。この配列に対しては、「隣接する2つの要素の絶対差が1である場合に限り」隣接要素同士を入れ替える(スワップする)ことができます。必要な回数だけスワップを繰り返せるとして、このnumsを昇順にソートできるかどうかを判定するのが目的です。例えば、入力が nums = [1, 0, 3, 2, 5, 4] の場合、出力はTrueになります。これは、ペア (1, 0)、(3, 2)、(5, 4) をそれぞれスワップすることで、[0, 1, 2, 3, 4, 5] というソート済みの配列を作れるため
-
Pythonでベクトルxを90度回転・加算してベクトルyに到達できるか判定するアルゴリズム
2次元平面上に3つのベクトル x、y、z があるとします。ベクトル x を起点として、「90度(時計回り)の回転」または「ベクトル z の加算」を必要な回数だけ繰り返すことで、ベクトル y に到達できるかどうかを判定するのがこの問題です。 たとえば、入力が x = (-4, -2)、y = (-1, 2)、z = (-2, -1) である場合、出力は True になります。x に対して z を加算する操作と 90 度の時計回り回転を組み合わせることで、y = (-1, 2) の位置に到達できるからです。 解法のアプローチ この問題は、次の手順に沿って解くことができます。 1. util()