Pythonで区間リストから重複しない期間の合計を求めるプログラム
各要素が区間 [start, end](両端を含む)を表すリストのリストがあるとします。このとき、これらの区間が実際にカバーしている重複しない期間の合計を求めたいと思います。
例えば、入力が intervals = [[2, 11], [13, 31], [41, 61]] の場合を考えてみましょう。各区間がカバーする長さはそれぞれ以下のようになります。
- (11 − 2 + 1) = 10
- (31 − 13 + 1) = 19
- (61 − 41 + 1) = 21
これらの区間は互いに重なり合っていないため、合計は 10 + 19 + 21 = 50 となります。
解決のためのアプローチ
この問題は、区間をソートして隣接する区間を順次マージしていくことで効率的に解けます。手順は以下の通りです。
- 区間リストが空の場合は 0 を返します。
- 区間リストをソートします。
- 最初の区間を
[start, end]として取得します。 - 答えを格納する変数
ansを 0 で初期化します。 - 各区間
(s, e)について以下を繰り返します。s > endの場合(現在の区間と重ならない場合):ans += end - start + 1でこれまでの区間の長さを加算し、start = s、end = eとして新しい区間を開始します。- そうでない場合(重なる場合):
end = max(end, e)として現在の区間の終点を拡張します。
- ループ終了後、最後の区間の長さ
end - start + 1をansに加算します。 ansを返します。
実装例
以下のコードで具体的な実装を確認してみましょう。
class Solution:
def solve(self, intervals):
if not intervals:
return 0
intervals.sort()
start, end = intervals[0]
ans = 0
for s, e in intervals:
if s > end:
ans += end - start + 1
start = s
end = e
else:
end = max(end, e)
ans += end - start + 1
return ans
ob = Solution()
intervals = [[2, 11],[13, 31],[41, 61]]
print(ob.solve(intervals))入力
[[2, 11],[13, 31],[41, 61]]
出力
50
アルゴリズムのポイント
このアプローチの計算量は、ソートに O(n log n)、マージ処理に O(n) かかるため、全体として O(n log n) です。区間を先にソートしておくことで、隣接する区間との比較だけで済み、すべての区間同士の組み合わせを調べる必要がなくなります。また、重複する区間(例:[1, 5] と [3, 8])が含まれていても、max(end, e) によって正しく統合されるため、二重カウントを防げるのが特徴です。
-
Pythonでリストの累積和(累積合計)を求める方法
この記事では、リストの累積和(累積合計)を求める問題の解決策について詳しく解説します。問題文あるリストが与えられたとき、各要素までの累積和を格納した新しいリストを作成する必要があります。例えば、[10, 20, 30, 40, 50] というリストが与えられた場合、出力は [10, 30, 60, 100, 150] となります。これは、各位置でそれ以前の要素をすべて足し合わせた値です。実装例それでは、実際の実装を見ていきましょう。# 累積和を求める関数 def Cumulative(l): new = [] cumsum = 0 for element in l:
-
【Python入門】リストから一意の値(重複しない要素)だけを抽出して出力する方法
リストが与えられたとき、その中から重複を除いた一意の値(ユニークな要素)だけを取り出して表示するのが、この記事の目的です。Pythonを使えば、初心者でも簡単に実装できる定番の処理なので、ぜひマスターしておきましょう。実行例入力:A = [1, 2, 3, 4, 2, 1, 9] 出力:[1, 2, 3, 4, 9]リスト内に同じ値が複数回現れていても、出力されるのはそれぞれ1回だけです。アルゴリズムステップ1:ユーザーからリストを入力として受け取る。 ステップ2:空のリストを作成する。 ステップ3:元のリストの全要素を順番に走査する。 ステップ4:その要素がすでに一意のリストに存在するかどう