diff --git a/1011.Capacity To Ship Packages Within D Days.md b/1011.Capacity To Ship Packages Within D Days.md new file mode 100644 index 0000000..bf31c3e --- /dev/null +++ b/1011.Capacity To Ship Packages Within D Days.md @@ -0,0 +1,159 @@ +# 進め方 + +Step1 : 問題を解く。 + +Step2 : 他の人のPRを参照し、コメントする。 + +Step3 : 3回続けてエラーが出ないように書く。ドキュメントを参照する。 + +# 実践 + +## Step1 + +### 思考ログ + +やり方がまったくわからない。 + +あ、累積和を取りそう。 + +weights = [1,2,3,1,1], days = 4として + +prefix = [1,3,5,6,7] + +ここを二分探索するのかなあ、わからん。 + +## Step2 + +### 同じ問題を解いた人のプルリクを見る + +https://github.com/olsen-blue/Arai60/pull/44/files + +- 競プロではよくある問題らしい。 +- あー最小のweightを二分探索するのか。 +- なんか凄いアルゴリズムがあると思っていた。 +- こういう使い方もできるんですね。FFFTTTTとなるものの最小を求めることには使えそうですね。 + +```python +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + def can_shipped(max_weight): + total_days = 0 + i = 0 + while i < len(weights): + total_days += 1 + package = 0 + while i < len(weights): + if weights[i] + package > max_weight: + break + package += weights[i] + i += 1 + if total_days > days: + return False + return True + + lo = 0 + hi = sum(weights) + 1 + while lo < hi: + mid = (lo + hi) // 2 + if can_shipped(mid): + hi = mid + continue + lo = mid + 1 + return hi +``` + +これもbisectを用いて求められるらしい。面白い。 + +https://github.com/hroc135/leetcode/pull/42 + +- Pythonはintの大きさ気にしなくて良いの幸せな気持ちになりました。 +- dead codeは避けるhttps://github.com/TORUS0818/leetcode/pull/44#discussion_r1996702695 + +https://github.com/nittoco/leetcode/pull/47/files + +- Daysが0以下の処理はどうするか +- rangeの実装を読んでいる。 + - https://github.com/python/cpython/blob/9ad0c7b0f14c5fcda6bfae6692c88abb95502d38/Objects/rangeobject.c#L318 + +```python +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + def can_ship(capacity): + i = 0 + total_days = 0 + while i < len(weights): + loading = 0 + total_days += 1 + while i < len(weights): + if weights[i] + loading > capacity: + break + loading += weights[i] + i += 1 + if total_days > days: + return False + return True + return bisect_left(range(sum(weights) + 1), True, key=can_ship) +``` + +```python +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + if not days: + return -1 + + def can_ship(capacity): + needed_days = 1 + loading = 0 + for weight in weights: + if weight > capacity: + return False + if loading + weight <= capacity: + loading += weight + continue + needed_days += 1 + if needed_days > days: + return False + loading = weight + return True + + return min(weights) + bisect_left(range(min(weights), sum(weights) + 1), True, key=can_ship) +``` + +- bisect_left(range(max(weights), sum(weights) + 1), True, key=is_loadable_capacity) + - 部分的な区間の中の、相対的なindexを返してしまうので、+ max(weights)が必要になった。割と仕様を知らないといけないのが微妙そう。 + +## Step3 + +### 3回連続で再現できるようになる + +return bisect_left(range(sum(weights)), True, key=can_ship) + +range(3)は0,1,2を返すので、なんでsum(weights)でよいかわからなかったが、見つからなかったらsum(weights)を返すのか。range(3)でFFFなら3を返しますね。 + +最小のTが帰ってきてほしいのでsum + 1したいですね。 + +```python +class Solution: + def shipWithinDays(self, weights: List[int], days: int) -> int: + assert days + + def can_ship(capacity): + loading = 0 + required_days = 1 + for w in weights: + if w > capacity: + return False + loading += w + if loading <= capacity: + continue + required_days += 1 + loading = w + if required_days > days: + return False + return True + + return bisect_left(range(sum(weights) + 1), True,lo=max(weights), key=can_ship) +``` + + if w > capacity: + return False はなくても良いが、can_shipに何が来ても良いように。