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

Pythonでk日以内にすべてのスカイダイビング申込を処理するための最小飛行機定員を求めるプログラム

数値のリスト nums があるとします。各要素は、一緒にスカイダイビングをしたいグループの人数を表しています。また、もうひとつの値 k は、スカイダイビングの申し込みが可能な日数を表します。ここで、すべてのリクエストを k 日以内に処理できるようにするために必要な、飛行機の最小定員を求めます。

ただし、リクエストは与えられた順番どおりに処理しなければならず、飛行機は1日に1回しか飛べないものとします。

たとえば、入力が nums = [16, 12, 18, 11, 13]k = 3 の場合、出力は 28 になります。これは、28人乗りの飛行機を使えば、グループを [16, 12][18][11, 13] のように3日間に分けて処理できるからです。

解き方のアプローチ

この問題は二分探索(バイナリサーチ)を使うことで効率的に解けます。答えとなる最小定員の候補範囲は、「リスト内の最大値(それ未満だとどのグループも乗せられない)」から「全要素の合計値(1日で全部乗せる場合)」までです。この範囲に対して二分探索を行い、各候補値について k 日以内に収まるかどうかをシミュレーションで判定します。

具体的には、次の手順で進めます。

  • nums が空なら 0 を返す
  • 探索範囲の下限 startnums の最大値、上限 end を全要素の合計値に設定する
  • start < end の間、以下を繰り返す
    • mid := (start + end) / 2 を候補の定員とする
    • days := 1temp := 0 として初期化する
    • nums の各要素 num について、temp + num > mid なら日数を1増やして temp := num とし、そうでなければ temp := temp + num とする
    • 必要日数 daysk より大きければ start := mid + 1、そうでなければ end := mid とする
  • 最後に start を返す

実装例

以下は、上記のアルゴリズムを実装したPythonコードです。

class Solution:
    def solve(self, nums, k):
        if not nums:
            return 0

        start, end = max(nums), sum(nums)

        while start < end:
            mid = (start + end) // 2

            days = 1
            temp = 0
            for num in nums:
                if temp + num > mid:
                    days += 1
                    temp = num
                else:
                    temp += num

            if days > k:
                start = mid + 1
            else:
                end = mid

        return start

ob = Solution()
nums = [16, 12, 18, 11, 13]
k = 3
print(ob.solve(nums, k))

入力

[16, 12, 18, 11, 13], 3

出力

28

計算量について

このアルゴリズムの時間計算量は O(n × log S) です。ここで n はグループ数、S は全人数の合計です。二分探索の各ステップで配列を一度走査するため、貪欲法だけで全範囲を試す方法よりもはるかに効率的に最小定員を求められます。

  1. Pythonで1つの数を別の数に変換するのに必要な最小操作回数を求めるプログラム

    問題の概要 2つの整数 start と end(start < end)が与えられます。次の2種類の操作のみを使って start を end に変換するとき、必要な操作の最小回数を求めるプログラムを作成しましょう。 数値に 1 を加える(インクリメント) 数値に 2 を掛ける 例として、start = 5、end = 11 の場合を考えます。5 に 2 を掛けて 10 とし、そこへ 1 を加えれば 11 になるため、答えは 2 回となります。 解き方のアプローチ この問題は、start から順に操作を試すよりも、end から逆算していく貪欲法(グリーディ法)が有効です。end が偶

  2. Pythonで数の因子の最小合計を求めるプログラム|素因数分解の考え方

    本記事では、与えられた整数について、積が元の数と等しくなる因子の組み合わせの中から合計が最小となる値を求める方法を、Pythonのコード例とともに解説します。 問題定義 入力として1つの整数が与えられます。この数を複数の因子の積として表したとき、因子の合計が最小になるケースを求めてください。 すべての因子の組み合わせを網羅的に調べて合計を比較する方法もありますが、実はもっとシンプルで効率的なアプローチが存在します。 考え方:素因数の合計が最小になる 鍵となるのは次の性質です。積が一定の値になるとき、因子の合計が最小になるのは、すべての因子を素数まで分解した場合(素因数分解した場合)です。