Pythonで一定速度で走行した最長区間(サブリスト)の長さを求めるアルゴリズム
等間隔の時間ごとに記録された車の位置を表す数値のリストが与えられたとき、車が一定の速度で走行していた最も長い連続区間(サブリスト)のサイズを求める問題を考えてみましょう。
例えば、入力が positions = [0, 4, 8, 12, 6, 4, 0] の場合、出力は 4 になります。これは部分リスト [0, 4, 8, 12] の間、各ステップでの移動距離が常に「4」で一定だからです。
解法のアプローチ
この問題は、隣接する2点間の移動距離を順番に比較していくことで解決できます。具体的な手順は以下の通りです。
- 変数
j = 1で走査を開始します。 - 最大カウント
max_cnt = 0、現在のカウントcurrent = 0を初期化します。 - 最初の2点間の距離
distance = |positions[0] - positions[1]|を基準として設定します。 jがリストの末尾に達するまで、以下を繰り返します。- 直前の位置
prev = positions[j - 1]を取得します。 distanceが|positions[j] - prev|と等しければ、速度が一定なのでcurrentを +1 します。- 等しくなければ、
max_cntを更新し、currentを 1 にリセットして、新しいdistanceを設定します。 - 毎回
max_cnt = max(max_cnt, current)で最大値を更新します。
- 直前の位置
- 最後に
max_cnt + 1を返します(区間の要素数は「移動回数 + 1」となるため)。
実装例
それでは、実際のPythonコードを見てみましょう。
class Solution:
def solve(self, positions):
j = 1
max_cnt = 0
current = 0
distance = abs(positions[0] - positions[1])
while j < len(positions):
prev = positions[j - 1]
if distance == abs(positions[j] - prev):
current += 1
else:
max_cnt = max(max_cnt, current)
current = 1
distance = abs(positions[j] - prev)
max_cnt = max(max_cnt, current)
j += 1
return max_cnt + 1
ob = Solution()
positions = [0, 4, 8, 12, 6, 4, 0]
print(ob.solve(positions))入力
[0, 4, 8, 12, 6, 4, 0]
出力
4
計算量について
このアルゴリズムはリストを一度だけ走査するため、時間計算量は O(n)、追加のメモリ使用量は定数であるため空間計算量は O(1) となります。位置データの件数が多くても効率的に処理できるのが特徴です。
-
Pythonでグラフ内の最大クリークの最小サイズを求めるプログラム
問題概要 グラフが与えられたとき、そのグラフに含まれる最大クリークの最小サイズを求める問題を考えます。ここで「クリーク」とは、グラフの頂点部分集合のうち、任意の2つの頂点が必ず隣接している(つまり、すべての頂点ペア間に辺が存在する)ものを指します。 最大クリークを求める問題は多項式時間では解けないことが知られているため(NP困難問題)、小規模なグラフについてノード数とエッジ数が与えられた場合には、工夫したアルゴリズムで最大クリークのサイズを導き出す必要があります。 例えば、入力が nodes = 4、edges = 4 の場合、出力は 2 となります。このグラフでは、クリークの最大サイズは 2
-
Pythonでグリッド内のボールの着地位置を求めるプログラム
問題概要 m × n のグリッドボックスを考えます。各セルには、左上から右下、もしくは右上から左下へ向けて斜めの板が設置されています。グリッドの上端からボールを落とし、それぞれのボールが底まで到達できるか、そしてどの列に着地するのかを求めるのがこの問題です。 グリッドは行列として与えられ、各セルの値は板の向きを表します。 1: 左上から右下へ下る斜めの板 -1: 右上から左下へ下る斜めの板 n 個のボールを上端の各列から順に落としたとき、底に到達したボールの着地列を答えとして返します。途中で側面の壁に当たったり、V字型の溝にはまって動けなくなったボールについては -1 を出力します。 3