diff --git a/0875.Koko-Eating-Bananas/memo.md b/0875.Koko-Eating-Bananas/memo.md new file mode 100644 index 0000000..0202473 --- /dev/null +++ b/0875.Koko-Eating-Bananas/memo.md @@ -0,0 +1,28 @@ +# 875. Koko Eating Bananas + +## step1 +二分探索を思いつく。時間計算量はO(nlog max(piles))。17mほど。最小値と最大値を何度か間違えた(ガチャを引いてしまった)。 + +とりあえず書いた答えを残す。 + +改善する。 + +上限と下限を単純に 1, max(piles)とした方が可読性が上がるが、速度は落ちる。 + +## step2 +二分探索を手で書く + +https://leetcode.com/problems/koko-eating-bananas/solutions/7047251/simple-solution-by-harshita_114-3c0a/ + +can_eat_all の判定はfor文を使えば早期終了できる場合があるのか + +実際の実行時間はジェネレータ表記の方が早かった + +https://github.com/yamashita-ki/codingTest/pull/15 + +https://github.com/Exzrgs/LeetCode/pull/45/changes + +https://github.com/TaisukeFujise/leetcode_tafujise/pull/16 + +## step3 +今回は省略で良いだろう diff --git a/0875.Koko-Eating-Bananas/step1.py b/0875.Koko-Eating-Bananas/step1.py new file mode 100644 index 0000000..ccd6e7c --- /dev/null +++ b/0875.Koko-Eating-Bananas/step1.py @@ -0,0 +1,16 @@ +import bisect + + +class Solution: + def minEatingSpeed(self, piles: List[int], h: int) -> int: + def can_eat_all(k): + return sum(((pile + k - 1) // k for pile in piles)) <= h + + candidate = range( + max(min(piles) // h, 1), + max((max(piles) * 2 - 1) // (h // len(piles)), 1) + 1, + ) + index = bisect.bisect_left( + range(len(candidate)), True, key=lambda index: can_eat_all(candidate[index]) + ) + return candidate[index] diff --git a/0875.Koko-Eating-Bananas/step1_revised.py b/0875.Koko-Eating-Bananas/step1_revised.py new file mode 100644 index 0000000..607ff9f --- /dev/null +++ b/0875.Koko-Eating-Bananas/step1_revised.py @@ -0,0 +1,18 @@ +import bisect + + +class Solution: + def minEatingSpeed(self, piles: list[int], h: int) -> int: + if not piles: + return 0 + + def can_eat_all(k): + return sum(((pile + k - 1) // k for pile in piles)) <= h + + max_candidate = max((max(piles) * 2 - 1) // (h // len(piles)), 1) + min_candidate = max(min(piles) // h, 1) + candidate = range(min_candidate, max_candidate + 1) + index = bisect.bisect_left( + range(len(candidate)), True, key=lambda index: can_eat_all(candidate[index]) + ) + return candidate[index] diff --git a/0875.Koko-Eating-Bananas/step2.py b/0875.Koko-Eating-Bananas/step2.py new file mode 100644 index 0000000..389cabd --- /dev/null +++ b/0875.Koko-Eating-Bananas/step2.py @@ -0,0 +1,18 @@ +class Solution: + def minEatingSpeed(self, piles: list[int], h: int) -> int: + if not piles: + return 0 + + def can_eat_all(k): + return sum(((pile + k - 1) // k for pile in piles)) <= h + + left = max(min(piles) // h, 1) + right = max((max(piles) * 2 - 1) // (h // len(piles)), 1) + 1 + while left < right: + mid = left + (right - left) // 2 + if not can_eat_all(mid): + left = mid + 1 + else: + right = mid + + return left diff --git a/0875.Koko-Eating-Bananas/step2_early_return.py b/0875.Koko-Eating-Bananas/step2_early_return.py new file mode 100644 index 0000000..7c1f2d5 --- /dev/null +++ b/0875.Koko-Eating-Bananas/step2_early_return.py @@ -0,0 +1,23 @@ +class Solution: + def minEatingSpeed(self, piles: list[int], h: int) -> int: + if not piles: + return 0 + + def can_eat_all(k): + hours = 0 + for i, pile in enumerate(piles): + hours += (pile + k - 1) // k + if hours + (len(piles) - i - 1) > h: + return False + return True + + left = max(min(piles) // h, 1) + right = max((max(piles) * 2 - 1) // (h // len(piles)), 1) + 1 + while left < right: + mid = left + (right - left) // 2 + if not can_eat_all(mid): + left = mid + 1 + else: + right = mid + + return left diff --git a/0875.Koko-Eating-Bananas/step2_revised.py b/0875.Koko-Eating-Bananas/step2_revised.py new file mode 100644 index 0000000..a2cfa2f --- /dev/null +++ b/0875.Koko-Eating-Bananas/step2_revised.py @@ -0,0 +1,18 @@ +class Solution: + def minEatingSpeed(self, piles: list[int], h: int) -> int: + if not piles: + return 0 + + def can_eat_all(k): + return sum(((pile + k - 1) // k for pile in piles)) <= h + + left = max(min(piles) // h, 1) + right = max((max(piles) * 2 - 1) // (h // len(piles)), 1) + 1 + while left < right: + mid = (left + right) // 2 + if not can_eat_all(mid): + left = mid + 1 + else: + right = mid + + return left