Pythonで全乗客の乗車・降車が車両の定員内で可能かどうかを判定するプログラム
問題の概要
requested_trips という行列(リスト)があるとします。各行は [start_x, end_x, num_passengers] の形式で構成されており、これとは別に車両の定員を表す capacity(容量)の値が与えられています。各トリップは「位置 start_x で num_passengers 人の乗客を乗せ、end_x で全員を降ろす」という乗降リクエストを意味します。
車は与えられた定員を持ち、位置 x = 0 から出発します。ただし、車は右方向(正の方向)にしか移動できないものとします。このとき、すべての乗客を乗せて降ろすことが可能かどうかを判定するのが目的です。
例として、入力が trips = [[1, 25, 2], [3, 4, 3], [5, 12, 3]]、capacity = 6 の場合、出力は True となります。
解決のアプローチ
この問題は、いわゆる「イベント方式(スイープライン法)」と呼ばれる考え方で効率的に解けます。乗車地点では乗客数が増え、降車地点では減るため、すべての乗降イベントを位置順に並べてシミュレーションすればよいのです。
具体的には、以下の手順に従います。
空のリスト
eventsを作成します。trips内の各要素(sx, ex, np)について、次の処理を行います。ペア
(sx, np)をeventsの末尾に追加します(乗車イベント)。ペア
(ex, -np)をeventsの末尾に追加します(降車イベント)。
現在の乗客数を表す変数
carryingを 0 で初期化します。eventsをソートし、各ペア(loc, delta)を順番に処理します。carryingにdeltaを加算します。carryingがcapacityを超えた時点でFalseを返します。
すべてのイベントを問題なく処理できたら
Trueを返します。
ポイントは、タプルをソートすると同じ位置のイベントでは負の値(降車)が正の値(乗車)より先に処理される点です。これにより、「先に降ろしてから乗せる」という自然な挙動が自動的に実現され、定員の判定が正確になります。
実装例
それでは、理解を深めるために実際のコードを見てみましょう。
class Solution:
def solve(self, trips, capacity):
events = []
for sx, ex, np in trips:
events.append((sx, np))
events.append((ex, -np))
carrying = 0
for loc, delta in sorted(events):
carrying += delta
if carrying > capacity:
return False
return True
ob = Solution()
trips = [
[1, 25, 2],
[3, 4, 3],
[5, 12, 3]
]
capacity = 6
print(ob.solve(trips, capacity))
入力
trips = [ [1, 25, 2], [3, 4, 3], [5, 12, 3] ] capacity = 6
出力
True
計算量について
トリップの数を N とすると、イベントは 2N 個生成され、ソートに O(N log N)、その後の走査に O(N) かかるため、全体の時間計算量は O(N log N) です。単純に各区間ごとに乗客数を数える O(N²) の方法よりも大幅に高速で、大量のリクエストにも対応できます。
-
Pythonで二分木が対称木(シンメトリックツリー)かどうかを判定するプログラム
ある二分木が与えられたとき、その木が対称木(シンメトリックツリー)であるかどうかを判定します。対称木とは、鏡像(左右反転した像)をとったときに元の木と完全に一致するような木のことです。例えば、左右の子部分木が互いに鏡写しの関係になっている木は対称木とみなされます。この判定を行うためのアプローチは以下の通りです。解法の考え方再帰的に処理を行う関数 solve(root, root) を呼び出します。同じノードを2つの引数として渡すのがポイントです。比較対象の2つのノード(node1 と node2)がどちらも空(None)の場合、True を返します。どちらか一方だけが空の場合、構造が一致してい
-
Pythonで与えられたグラフが2部グラフかどうかを判定するプログラム
2部グラフとは無向グラフが与えられたとき、そのグラフが2部グラフ(バイパータイトグラフ)であるかどうかを判定する方法を解説します。2部グラフとは、グラフのすべての頂点を2つの集合 A と B に分割でき、グラフ内のすべての辺 {u, v} が必ず一方の端点 u が集合 A、もう一方の端点 v が集合 B に属するようなグラフのことです。つまり、同じ集合内の頂点同士を結ぶ辺(A-A や B-B)が一切存在しないグラフです。例として、次のようなグラフを考えてみましょう。この場合、頂点 [0, 4] を集合 A に、[1, 2, 3] を集合 B に分類できます。すべての辺は A から B、または