Pythonで一意な要素からなる最長の連続サブリストの長さを求める方法
重複のない(すべての要素が一意な)数値リスト nums が与えられたとき、その中から「連続する整数で構成される最長の部分リスト」の長さを求める問題を考えます。
例えば、nums = [3, 6, 7, 5, 4, 9] の場合、答えは 5 になります。これは、部分リスト [3, 6, 7, 5, 4] が 3 から 7 までの連続する整数をすべて含んでいるためです。
解法のアプローチ
この問題は、すべての部分リストを走査する O(n²) のアプローチで効率よく解けます。ポイントは以下の通りです。
- 各開始位置
iについて、終了位置jを右へ伸ばしながら、範囲内の最小値lhsと最大値rhsを順次更新します。 - 要素がすべて一意であるため、「最大値 − 最小値 = 要素数 − 1」が成り立つとき、その部分リストは連続する整数で構成されていると判定できます。
- 条件を満たすたびに、これまでの最長の長さを記録しておき、最後にその値を返します。
具体的な手順
ret := 0(答えを格納する変数)で初期化するiを 0 から リストの末尾まで繰り返すlhs := nums[i]、rhs := nums[i]とするjをiから リストの末尾まで繰り返すlhs := min(lhs, nums[j])rhs := max(rhs, nums[j])rhs - lhs == j - iならば、ret := max(ret, j - i + 1)
retを返す
実装例
以下のPythonコードで実際の動作を確認できます。
def solve(nums):
ret = 0
for i in range(len(nums)):
lhs = nums[i]
rhs = nums[i]
for j in range(i, len(nums)):
lhs = min(lhs, nums[j])
rhs = max(rhs, nums[j])
if rhs - lhs == j - i:
ret = max(ret, j - i + 1)
return ret
nums = [3, 6, 7, 5, 4, 9]
print(solve(nums))
入力
[3, 6, 7, 5, 4, 9]
出力
5
計算量について
このアルゴリズムの時間計算量は O(n²)、空間計算量は O(1) です。二重ループで全ての部分リストを確認しますが、最小値・最大値のみを保持するため追加のメモリはほとんど不要です。入力リストのサイズが数千程度であれば十分実用的な速度で動作します。
-
Pythonで二分木の最長連続パスの長さを求めるアルゴリズムと実装
二分木(バイナリツリー)が与えられたとき、木の中にある最長の連続パスの長さを求めることを考えます。ここでの「連続パス」とは、隣り合うノードの値が1ずつ増加、または1ずつ減少していくようなノードの並びのことです。問題の例例えば、次のような二分木が入力として与えられたとします。この場合、最も長い連続シーケンスは [2, 3, 4, 5, 6] となるため、出力は 5 になります。解き方のアプローチこの問題は、再帰的に各ノードを訪問しながら「増加パス」と「減少パス」の長さを追跡することで解けます。手順は以下の通りです。ルートがnullの場合は0を返す最大パス長を記録する変数 maxPath を0で初
-
Pythonで同じ文字が連続する最長部分文字列の長さを求めるプログラム
この記事では、Pythonを使って「同じ文字が連続している最長の部分文字列の長さ」を求める方法を解説します。 例えば、入力が abbbaccabbbba の場合、b が4つ連続して並んでいる箇所があるため、出力は 4 となります。 解法のアプローチ この問題は、文字列を先頭から順番に走査し、隣接する2つの文字を比較することで解決できます。具体的な手順は以下のとおりです。 文字列 s の長さが 0 の場合は、そのまま 0 を返します。 s の末尾に空白文字を1つ追加します。これは、ループ処理の際に文字列の最後にある連続グループも確実に確定させるためのテクニックです。 カウンター ct と一時