Pythonで最長連続シーケンスの長さを求めるアルゴリズムと実装方法
問題概要
ソートされていない数値の配列が与えられたとき、その中から連続する要素で構成される最長シーケンスの長さを見つける問題を考えてみましょう。ここでいう「連続」とは、値が1ずつ増えていく数列(例:4, 5, 6, 7)のことを指します。
例えば、入力が nums = [70, 7, 50, 4, 6, 5] の場合、最も長い連続シーケンスは [4, 5, 6, 7] となるため、答えは 4 になります。
解法のアプローチ
この問題は、以下の手順で効率的に解くことができます。
- まず、配列をセット(set)に変換して重複を除去します。これにより、要素の存在確認が O(1) で行えるようになります。
- 各要素
numについて、「num - 1がセットに存在しない場合」、その要素は連続シーケンスの始点であると判断できます。 - 始点から順に
num + 1、num + 2… と値が存在するかを確認し、シーケンスの長さをカウントします。 - カウントした長さの最大値を記録し、最終的にそれを返します。
この「始点からのみ探索を開始する」という工夫により、同じシーケンスを何度も走査することを避けられます。
実装例
class Solution:
def solve(self, nums):
nums = set(nums)
max_cnt = 0
for num in nums:
if num - 1 not in nums:
cnt = 0
while num in nums:
num += 1
cnt += 1
max_cnt = max(max_cnt, cnt)
return max_cnt
ob = Solution()
nums = [70, 7, 50, 4, 6, 5]
print(ob.solve(nums))
入力
[70, 7, 50, 4, 6, 5]
出力
4
計算量について
一見すると二重ループがあるため O(n²) に見えますが、実際には各要素は高々1回しか走査されないため、時間計算量は O(n) です。これは、内側の while ループが開始されるのは「シーケンスの始点」だけだからです。
また、セットへの変換に O(n) の空間計算量が必要となります。ソートを使う方法(O(n log n))よりも高速に動作するのがこのアルゴリズムの大きな利点です。
-
Pythonでn分木の最長パスの長さを求めるプログラムの書き方
各要素が (u, v) という形式を持ち、u が v の親であることを表す辺リストが与えられているとします。このとき、木の中で最も長いパスの長さを求める必要があります。ここでいうパスの長さとは、「そのパスに含まれるノードの総数 + 1」のことです。 たとえば、入力が下図のような n 分木だった場合を考えてみましょう。 この場合の出力は 5 になります。なぜなら、パス [1, 4, 5, 7] には合計 4 つのノードが含まれており、パスの長さは 1 + 4 = 5 となるからです。 解き方のアプローチ この問題は、幅優先探索(BFS)を2回実行するという定番テクニックで効率よく解けます。まず
-
Pythonで二分木の最長連続パスの長さを求めるアルゴリズムと実装
二分木(バイナリツリー)が与えられたとき、木の中にある最長の連続パスの長さを求めることを考えます。ここでの「連続パス」とは、隣り合うノードの値が1ずつ増加、または1ずつ減少していくようなノードの並びのことです。問題の例例えば、次のような二分木が入力として与えられたとします。この場合、最も長い連続シーケンスは [2, 3, 4, 5, 6] となるため、出力は 5 になります。解き方のアプローチこの問題は、再帰的に各ノードを訪問しながら「増加パス」と「減少パス」の長さを追跡することで解けます。手順は以下の通りです。ルートがnullの場合は0を返す最大パス長を記録する変数 maxPath を0で初