Python
 Computer >> コンピューター >  >> プログラミング >> Python

Pythonで最長連続シーケンスの長さを求めるアルゴリズムと実装方法

問題概要

ソートされていない数値の配列が与えられたとき、その中から連続する要素で構成される最長シーケンスの長さを見つける問題を考えてみましょう。ここでいう「連続」とは、値が1ずつ増えていく数列(例:4, 5, 6, 7)のことを指します。

例えば、入力が nums = [70, 7, 50, 4, 6, 5] の場合、最も長い連続シーケンスは [4, 5, 6, 7] となるため、答えは 4 になります。

解法のアプローチ

この問題は、以下の手順で効率的に解くことができます。

  1. まず、配列をセット(set)に変換して重複を除去します。これにより、要素の存在確認が O(1) で行えるようになります。
  2. 各要素 num について、「num - 1 がセットに存在しない場合」、その要素は連続シーケンスの始点であると判断できます。
  3. 始点から順に num + 1num + 2… と値が存在するかを確認し、シーケンスの長さをカウントします。
  4. カウントした長さの最大値を記録し、最終的にそれを返します。

この「始点からのみ探索を開始する」という工夫により、同じシーケンスを何度も走査することを避けられます。

実装例

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))よりも高速に動作するのがこのアルゴリズムの大きな利点です。

  1. Pythonでn分木の最長パスの長さを求めるプログラムの書き方

    各要素が (u, v) という形式を持ち、u が v の親であることを表す辺リストが与えられているとします。このとき、木の中で最も長いパスの長さを求める必要があります。ここでいうパスの長さとは、「そのパスに含まれるノードの総数 + 1」のことです。 たとえば、入力が下図のような n 分木だった場合を考えてみましょう。 この場合の出力は 5 になります。なぜなら、パス [1, 4, 5, 7] には合計 4 つのノードが含まれており、パスの長さは 1 + 4 = 5 となるからです。 解き方のアプローチ この問題は、幅優先探索(BFS)を2回実行するという定番テクニックで効率よく解けます。まず

  2. Pythonで二分木の最長連続パスの長さを求めるアルゴリズムと実装

    二分木(バイナリツリー)が与えられたとき、木の中にある最長の連続パスの長さを求めることを考えます。ここでの「連続パス」とは、隣り合うノードの値が1ずつ増加、または1ずつ減少していくようなノードの並びのことです。問題の例例えば、次のような二分木が入力として与えられたとします。この場合、最も長い連続シーケンスは [2, 3, 4, 5, 6] となるため、出力は 5 になります。解き方のアプローチこの問題は、再帰的に各ノードを訪問しながら「増加パス」と「減少パス」の長さを追跡することで解けます。手順は以下の通りです。ルートがnullの場合は0を返す最大パス長を記録する変数 maxPath を0で初