1011. Capacity To Ship Packages Within D Days
はじめに
転職も見据えて、LeetCodeをコツコツ解いていくことにした。
解くだけでは定着しそうにないので、格闘したLeetCodeの問題をメモしていく。
問題
指定の日にちで全ての荷物を運ぶのに必要な、最低限の容量を求める。
考えの流れ
条件を整理してみる。
・容量としてあり得るのが、荷物の重さの最大値から荷物の合計の重さの間
・制約条件的にシンプルな全探索は無理
解法に紐づけられないのでヒントを見る
→バイナリーサーチを使えとのこと。
→リスト自体は順序で並んでいない。同整理するか。
→weightsリストではなく、容量のリストをバイナリーサーチするか。
・オーダーは、荷物の数をnとすると最悪でO(n⋅log(sum(weights)−max(weights)))?
・やってみよう。
コード
from typing import List
class Solution:
def check_avairability(self, days, cap_b, weights):
w_b = 0 # 現在の船の積載量
w_d = 1 # 現在の日数(1日目から)
for weight in weights:
if w_b + weight <= cap_b:
w_b += weight
else:
if w_d < days:
w_d += 1
w_b = weight
else:
return False
return True
def shipWithinDays(self, weights: List[int], days: int) -> int:
left = max(weights)
right = sum(weights)
while left < right:
mid = (left + right) // 2
if self.check_avairability(days, mid, weights): # `mid` の容量で運べるか確認
right = mid
else:
left = mid + 1 # 運べないなら、容量を大きく
return left # 最小の容量が left に収束
まとめ
・バイナリーサーチに帰着できなかった
・何かソートされた配列の大小を比較していくようなときにはバイナリーサーチを思い浮かべるようにしたい
・最初DP?と思ったけど、どう実現するのかわからずやめた
・バイナリサーチのleft,rightをmidからどう定義するかもふわふわしているので要復習