diff --git a/1011/memo.md b/1011/memo.md new file mode 100644 index 0000000..92b613c --- /dev/null +++ b/1011/memo.md @@ -0,0 +1,32 @@ +# 1011. Capacity To Ship Packages Within D Days + +https://leetcode.com/problems/capacity-to-ship-packages-within-d-days/description/ + +TODO: 二分探索を自分で書く + +- capacityを指定すればそれが可能かはO(N)で判定できる +- 上限をどのように定めるかが問題。単純にsum(weights)としたとき220ms、minを使ったとき119msとなった。 +- 問題のWeight上限を使う方法は正攻法なのだろうか +- 自力で解法を思いついたが、二分探索のヒントがあったから + +n = len(weights), M = maximum_valueとすると +- 時間計算量: O(n*log(M)) +- 空間計算量: O(1) (入力は含めない) + + +コメント集に該当箇所はない + +https://github.com/naoto-iwase/leetcode/pull/27/changes + +capacityの下限はmax(weights)とできるのか +- これを反映してsol2.pyとしたが、149msとなり逆に遅くなった +- maxをとるO(n)の操作に余分な時間がかかるケースが多いのだろう。二分探索は途中で打ち切られるのでそれほど重くない。 + + +https://github.com/mamo3gr/arai60/blob/1011_capacity-to-ship-packages-within-d-days/1011_capacity-to-ship-packages-within-d-days/memo.md + +色々なコードがまとめられている + +https://github.com/h1rosaka/arai60/pull/46/changes + +上でも述べられているけど、 `for _ in range(days):` で書くこともできるのは思いつかなかった diff --git a/1011/sol1.py b/1011/sol1.py new file mode 100644 index 0000000..fd9b979 --- /dev/null +++ b/1011/sol1.py @@ -0,0 +1,23 @@ +import bisect + +MAXIMUM_WEIGHT = 500 + + +class Solution: + def shipWithinDays(self, weights: list[int], days: int) -> int: + def can_ship(capacity): + used_days = 1 + shipped_weight_on_current_day = 0 + for weight in weights: + if shipped_weight_on_current_day + weight <= capacity: + shipped_weight_on_current_day += weight + continue + used_days += 1 + if used_days > days or weight > capacity: + return False + shipped_weight_on_current_day = weight + return True + + maximum_value = min(sum(weights), MAXIMUM_WEIGHT * (len(weights) // days + 1)) + + return bisect.bisect_left(range(1, maximum_value), True, key=can_ship) + 1 diff --git a/1011/sol2.py b/1011/sol2.py new file mode 100644 index 0000000..2285c3a --- /dev/null +++ b/1011/sol2.py @@ -0,0 +1,25 @@ +import bisect + + +class Solution: + def shipWithinDays(self, weights: list[int], days: int) -> int: + def can_ship(capacity): + used_days = 1 + shipped_weight_on_current_day = 0 + for weight in weights: + if shipped_weight_on_current_day + weight <= capacity: + shipped_weight_on_current_day += weight + continue + used_days += 1 + if used_days > days or weight > capacity: + return False + shipped_weight_on_current_day = weight + return True + + minimum_value = max(weights) + maximum_value = sum(weights) + + return ( + bisect.bisect_left(range(minimum_value, maximum_value), True, key=can_ship) + + minimum_value + ) diff --git a/1011/sol2_revised.py b/1011/sol2_revised.py new file mode 100644 index 0000000..4ca7a93 --- /dev/null +++ b/1011/sol2_revised.py @@ -0,0 +1,25 @@ +import bisect + + +class Solution: + def shipWithinDays(self, weights: list[int], days: int) -> int: + def can_ship(capacity): + used_days = 1 + total_weight = 0 + for weight in weights: + if total_weight + weight <= capacity: + total_weight += weight + continue + used_days += 1 + if used_days > days or weight > capacity: + return False + total_weight = weight + return True + + minimum_value = max(weights) + maximum_value = sum(weights) + + return ( + bisect.bisect_left(range(minimum_value, maximum_value), True, key=can_ship) + + minimum_value + )