Pythonで、部分リストを並べ替えるだけでリスト全体が昇順にソートされる最短の範囲を見つける方法
数値のリスト nums が与えられたとき、その一部を並べ替えるだけでリスト全体が昇順にソートされるような、最短の部分リスト(サブリスト)の長さを求める問題について解説します。
問題の例
たとえば、入力が nums = [1, 2, 5, 4, 9, 10] の場合、出力は 2 になります。これは、部分リスト [5, 4] を並べ替えるだけで、リスト全体が [1, 2, 4, 5, 9, 10] という昇順の状態になるためです。
解き方のアルゴリズム
この問題は、次の手順で解くことができます。
f := -1、l := -1として初期化するlst :=リストnumsをソートしたコピーを作成するiを 0 からnumsのサイズまで繰り返すnums[i]とlst[i]が異なる場合fが -1 であれば、f := iを代入- それ以外の場合は、
l := iを代入
- ループ終了後、
lとfがどちらも -1 であれば0を返す(すでにソート済みであることを意味する) - それ以外の場合は、
l - f + 1を返す
考え方のポイント
このアプローチの鍵となるのは、元のリストとソート済みリストを位置ごとに比較することです。最初に不一致が発生した位置が並べ替えが必要な範囲の始点となり、最後に不一致が発生した位置が終点となります。この2つの位置に挟まれた区間の長さが、求める答えになります。
実装例
以下の実装を見ると、理解がより深まるでしょう。
class Solution:
def solve(self, nums):
f = -1
l = -1
lst = sorted(nums)
for i in range(len(nums)):
if nums[i] != lst[i]:
if f == -1:
f = i
else:
l = i
if l == -1 and f == -1:
return 0
return l - f + 1
ob = Solution()
print(ob.solve([1, 2, 5, 4, 9, 10]))
入力
[1, 2, 5, 4, 9, 10]
出力
2
計算量について
このアルゴリズムでは、リストのソートに O(n log n) の時間がかかるため、全体の時間計算量は O(n log n) となります。また、ソート済みのコピーを保持する必要があるため、空間計算量は O(n) です。
-
Pythonでソート済みリスト内のすべてのペアの絶対差の合計を求めるプログラム
ソートされた数値リスト nums が与えられたとき、リスト内のすべての数値ペアの絶対差の合計を求めることを考えます。ここで、(i, j) と (j, i) は異なるペアとして扱います。答えが非常に大きくなる場合は、結果を 10^9+7 で割った余りを返します。例えば、nums = [2, 4, 8] の場合、|2 - 4| + |2 - 8| + |4 - 2| + |4 - 8| + |8 - 2| + |8 - 4| を計算することになるため、出力は 24 となります。解法のアプローチこの問題を効率的に解くために、以下の手順に従います。m = 10^9 + 7 とします。total を 0
-
【Python】リスト内の2つの数値を足して合計がkになるペアを探すプログラム
数値のリスト nums ともう一つの数値 k が与えられたとき、リスト内の任意の2つの数値を足した合計が k と一致するかどうかを判定するプログラムを作成します。ただし、同じ要素を2回使用することはできません。また、数値には負の数や0が含まれる場合もあります。例えば、入力が nums = [45, 18, 9, 13, 12]、k = 31 の場合、18 + 13 = 31 となるため、出力は True になります。解法のアプローチこの問題は「セット(集合)」を使うことで効率的に解けます。各数値に対して、それとペアになるべき値(k - num、いわゆる補数)を事前にセットへ記録しておき、後から