Pythonで接頭辞和がすべて正になるように先頭へ挿入する最小の値を求めるプログラム
数値のリスト nums が与えられたとします。このリストの先頭に挿入することで、結果として得られるリストの接頭辞和(プレフィックスサム)がすべて0より大きくなるような、最小の正の値を求めるのがこの問題の目的です。
問題の例
たとえば、入力が nums = [3, -6, 4, 3] の場合、出力は 4 になります。これは、4 をリストの先頭に挿入すると [4, 3, -6, 4, 3] となり、その接頭辞和は [4, 7, 1, 5, 8] となって、すべての値が0より大きくなるためです。
解法のアプローチ
この問題は、次の手順で効率的に解くことができます。
- リスト
numsの先頭(インデックス0)に0を挿入します。 - インデックス1からリストの末尾まで順に走査し、各要素に対して
nums[i] = nums[i] + nums[i - 1]を実行して累積和(接頭辞和)を計算します。 - 最後に
1 - min(nums)を返します。これにより、接頭辞和の最小値がちょうど1になるように調整した値、つまり必要な最小の正の整数が得られます。
Pythonでの実装例
以下のコードで実際の動作を確認してみましょう。
def solve(nums):
nums.insert(0, 0)
for i in range(1, len(nums)):
nums[i] += nums[i - 1]
return 1 - min(nums)
nums = [3, -6, 4, 3]
print(solve(nums))入力
[3, -6, 4, 3]
出力
4
アルゴリズムのポイント
この手法の鍵となるのは、先頭に挿入すべき値 x を加えたとき、すべての接頭辞和に一律に x が加算されるという性質です。元のリストの接頭辞和の最小値を m とすると、x + m > 0 を満たす最小の正の整数 x は 1 - m となります。計算量は O(n) と非常に効率的で、大きなリストでも高速に処理できます。
-
Pythonで全ての点を接続するための最小コストを求めるプログラム
問題の概要(x, y) の形式で表される複数の点が格納された配列 points があるとします。2つの点 (xi, yi) と (xj, yj) を接続するコストは、それらの間のマンハッタン距離として定義されます。マンハッタン距離は次の式で計算できます。|xi − xj| + |yi − yj|この問題では、すべての点を接続するために必要な最小のコストを求める必要があります。入力例points = [(0,0), (3,3), (2,10), (6,3), (8,0)]この場合、出力は 22 になります。これは、各辺の距離がそれぞれ 6 + 5 + 3 + 8 = 22 となるように点同士を接
-
Pythonですべての出荷を完了するために必要な総コストを求めるプログラム
リストのリスト ports が与えられているとします。ここで ports[i] は、港 i が接続されている港の一覧を表します。さらに別のリストのリスト shipments もあり、その各要素は [i, j] という形式のシーケンスで、「港 i から港 j への出荷依頼」を意味します。港 i から港 j へ出荷するコストは、2つの港間の最短経路の長さとして定義されます。このとき、すべての出荷を完了させるために必要な総コストを求めるのが課題です。たとえば、入力が次のような場合を考えてみましょう。ports = [[1, 4],[2],[3],[0, 1],[]] shipments = [[1,