Pythonで最短の「ソートされていない連続部分配列」を見つける方法
整数配列が与えられたとき、「その部分配列だけを昇順にソートすれば、配列全体がソート済みの状態になる」という条件を満たす連続する部分配列の中で、最も短いものを求めてその長さを出力することを考えます。
例えば、配列が [2,6,4,8,10,9,15] の場合、答えは 5 になります。これは、[6,4,8,10,9] の部分だけを昇順に並べ替えると、配列全体が [2,4,6,8,9,10,15] と完全にソートされた状態になるためです。
解法のアプローチ
この問題は、次の手順で解くことができます。
- 元の配列
numsを昇順にソートしたコピーresを作成します。 - 各インデックス
iについてnums[i]とres[i]を比較し、値が異なる場合はそのインデックスをリストrに記録していきます。 rが空の場合、配列はすでにソート済みなので 0 を返します。- それ以外の場合、記録されたインデックスの範囲、すなわち
r[-1] - r[0] + 1(最後の要素 − 最初の要素 + 1)が求める最短部分配列の長さとなります。
Pythonでの実装例
以下のコードで実際の動作を確認できます。
class Solution:
def findUnsortedSubarray(self, nums):
res = sorted(nums)
r = []
for i in range(len(res)):
if nums[i] != res[i]:
r.append(i)
if len(r) == 0:
return 0
return r[-1] - r[0] + 1
ob1 = Solution()
print(ob1.findUnsortedSubarray([2,6,4,8,10,9,15]))
入力
[2,6,4,8,10,9,15]
出力
5
計算量の考察
この解法では、ソートに O(n log n)、全要素の比較に O(n) の時間が必要なため、全体の時間計算量は O(n log n) となります。また、ソート済みのコピーを保持するため、空間計算量は O(n) です。
なお、より効率化したい場合は、配列を左端と右端から一度ずつ走査し、順序が崩れている境界を直接特定する方法を使えば、O(n) 時間・O(1) 空間で解くことも可能です。
-
Pythonでターゲットノードを含む最短サイクルの長さを求める方法(BFS活用)
問題の概要有向グラフの隣接リストが与えられます。各インデックス i のリストには、ノード i から直接接続されているノードの一覧が格納されています。さらに、探索対象となる値(target)も与えられます。この課題では、target を含むサイクル(閉路)の中で最も短いものの長さを求めます。該当するサイクルが存在しない場合は -1 を返してください。具体例例えば、次のようなグラフが与えられたとします。graph = [[1, 4], [2], [3], [0, 1], []]target = 3 の場合、出力は 3 になります。これは、ノード 1 → 2 → 3 → 1 というサイクルが存在する
-
Pythonで2つの未ソートのリストをマージしてソート済みリストを作成する方法
ここでは、ユーザーが入力した2つのリストが与えられます。各リストの要素はソートされていない状態です。この記事の目的は、これら2つの未ソートのリストを1つにマージし、その後リスト全体を昇順に並べ替えることです。例入力: A[] = {100, 50, 150} B[] = {200, 30, 20} 出力: マージ後のリスト: {20, 30, 50, 100, 150, 200}アルゴリズムステップ1: まず、ユーザー入力による2つのリストを作成します。 ステップ2: 最終的なマージリストのサイズは「1つ目のリストのサイズ + 2つ目のリストのサイズ」になります。 ステップ3: s