diff --git a/1011. Capacity To Ship Packages Within D Days/1011. Capacity To Ship Packages Within D Days.md b/1011. Capacity To Ship Packages Within D Days/1011. Capacity To Ship Packages Within D Days.md new file mode 100644 index 0000000..8e8924b --- /dev/null +++ b/1011. Capacity To Ship Packages Within D Days/1011. Capacity To Ship Packages Within D Days.md @@ -0,0 +1,132 @@ +# 1011. Capacity To Ship Packages Within D Days +## STEP1 +- 何も見ずに解いてみる +- 船のキャパシティを range として用意し、days 以内で運び出せるかどうかを判定する。True となる最小のキャパシティを探索する。 + +```python +import bisect + + +MAX_WEIGHT = 500 +MAX_WEIGHT_LENGTH = 50_000 + + +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + def can_ship_within_days(ship_capacity: int) -> bool: + num_days = 1 + total_weight_at_a_day = 0 + for weight in weights: + if weight > ship_capacity: + return False + total_weight_at_a_day += weight + if total_weight_at_a_day <= ship_capacity: + continue + num_days += 1 + total_weight_at_a_day = weight + return num_days <= days + + return bisect.bisect_left( + range(MAX_WEIGHT * MAX_WEIGHT_LENGTH + 1), + True, + key=can_ship_within_days + ) +``` + +## STEP2 +### プルリクやドキュメントを参照 +- range を bisect_left の引数として良いかは自信がなかった。 + - https://docs.python.org/3/library/stdtypes.html#typesseq-range + - range は空間計算量 O(1) で、 common sequence operations としてランダムアクセスも実装されていそうなので、動く。 + +- https://github.com/olsen-blue/Arai60/pull/44/files + - 探索区間について、[max(weights), sum(weights)] でよい。船のキャパの下限を、全ての荷物一つが乗るサイズとすると、空の船に荷物が乗らない状況を考えなくて済む。 + - days が 0 の場合、STEP1のコードは MAX_WEIGHT * MAX_WEIGHT_LENGTH + 1 を返す。意味はないので 0 は ValueError とした方がよい。 + +```python +import bisect + + +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + if days <= 0: + raise ValueError("days must be positive.") + + def can_ship_within_days(ship_capacity: int) -> bool: + days_required = 1 + total_weight = 0 + for weight in weights: + total_weight += weight + if total_weight <= ship_capacity: + continue + days_required += 1 + total_weight = weight + return days_required <= days + + return bisect.bisect_left( + range(sum(weights) + 1), + True, + lo=max(weights), + key=can_ship_within_days + ) +``` + +練習として2分探索を書く。 +```python +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + if days <= 0: + raise ValueError("days must be positive.") + + def can_ship_within_days(ship_capacity: int) -> bool: + days_required = 1 + total_weight = 0 + for weight in weights: + total_weight += weight + if total_weight <= ship_capacity: + continue + days_required += 1 + total_weight = weight + return days_required <= days + + low = max(weights) + high = sum(weights) + while low < high: + middle = (low + high) // 2 + if can_ship_within_days(middle): + high = middle + else: + low = middle + 1 + return low +``` +## STEP3 +### 3回ミスなく書く +```python +import bisect + + +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + if days <= 0: + raise ValueError("days must be positive") + + def can_ship_within_days(ship_capacity: int) -> bool: + total_weight = 0 + days_required = 1 + for weight in weights: + total_weight += weight + if total_weight <= ship_capacity: + continue + days_required += 1 + total_weight = weight + return days_required <= days + + return bisect.bisect_left( + range(sum(weights) + 1), + True, + lo=max(weights), + key=can_ship_within_days + ) +``` + +3分,3分,3分で3回Accept