Koko loves to eat bananas.  There are N piles of bananas, the i-th pile has piles[i] bananas.  The guards have gone and will come back in H hours.
Koko can decide her bananas-per-hour eating speed of K.  Each hour, she chooses some pile of bananas, and eats K bananas from that pile.  If the pile has less than K bananas, she eats all of them instead, and won't eat any more bananas during this hour.
Koko likes to eat slowly, but still wants to finish eating all the bananas before the guards come back.
Return the minimum integer K such that she can eat all the bananas within H hours.
 
Example 1:
Input: piles = [3,6,7,11], H = 8
Output: 4
Example 2:
Input: piles = [30,11,23,4,20], H = 5
Output: 30
Example 3:
Input: piles = [30,11,23,4,20], H = 6
Output: 23

 
Constraints:

1 <= piles.length <= 10^4
piles.length <= H <= 10^9
1 <= piles[i] <= 10^9

Source: leetcode | Difficulty: MEDIUM
Tags: Sorting

Data structures

Starter code: class Solution:
    def minEatingSpeed(self, piles: List[int], H: int) -> int:
        

Solutions:
class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		bananas = sum(piles)
		K = bananas // H + (bananas % H != 0)
		while True:
			hours_needed = 0
			for pile in piles:
				hours_needed += pile // K
				if pile % K != 0:
					hours_needed += 1
			if hours_needed <= H:
				return K
			K += 1


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		total_bananas = sum(piles)
		(left, right) = (math.ceil(total_bananas / H), math.ceil(total_bananas / (H - len(piles) + 1)))
		while left < right:
			mid = (left + right) // 2
			if not sum([math.ceil(pile / mid) for pile in piles]) <= H:
				left = mid + 1
			else:
				right = mid
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def time_need(K):
			return sum((p // K + (1 if p % K else 0) for p in piles))
		low = max(1, sum(piles) // H)
		high = max(piles)
		while low < high:
			if time_need(low) <= H:
				return low
			low += 1
			mid = (low + high) // 2
			if time_need(mid) > H:
				low = mid + 1
			else:
				high = mid
		return low


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def helper(k):
			ret = 0
			for pile in piles:
				ret += math.ceil(pile / k)
				if ret > H:
					return False
			return True
		(l, r) = (1, max(piles))
		while l <= r:
			mid = l + (r - l) // 2
			if helper(mid):
				r = mid - 1
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		self.piles = piles
		(l, r) = (1, max(piles))
		while l <= r:
			K = (l + r) // 2
			if self.eat_time(K) <= H:
				r = K - 1
			else:
				l = K + 1
		return l

	def eat_time(self, K):
		cnt = 0
		for banana in self.piles:
			(q, mod) = divmod(banana, K)
			cnt += q
			if mod != 0:
				cnt += 1
		return cnt


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def enough(n):
			hrs = 0
			for i in piles:
				if n > i:
					hrs += 1
				elif i % n == 0:
					hrs += i // n
				else:
					hrs += i // n + 1
			return hrs <= H
		(l, r) = (1, sum(piles))
		while l < r:
			m = (l + r) // 2
			if not enough(m):
				l = m + 1
			else:
				r = m
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(left, right) = (1, max(piles))
		while left <= right:
			mid = left + (right - left) // 2
			if self.condition(piles, H, mid):
				right = mid - 1
			else:
				left = mid + 1
		return left

	def condition(self, piles, H, k):
		hours = 0
		for pile in piles:
			(div, rem) = divmod(pile, k)
			hours += div
			if rem != 0:
				hours += 1
		return hours <= H


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def can(K):
			cur = H
			for a in piles:
				cur -= a // K
				cur -= a % K != 0
			return cur >= 0
		(l, r) = (1, sum([a + 1 for a in piles]))
		while l < r:
			mid = (l + r) // 2
			if can(mid):
				r = mid
			else:
				l = mid + 1
		return l


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		end = max(piles)
		start = 1
		while start + 1 < end:
			mid = start + (end - start) // 2
			if self.possible(mid, piles, H):
				end = mid
			else:
				start = mid
		if self.possible(start, piles, H):
			return start
		if self.possible(end, piles, H):
			return end

	def possible(self, eat_load, total_load, hour):
		return sum([math.ceil(-k / -eat_load) for k in total_load]) <= hour


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = sum(piles) // H
		hi = max(piles)
		if len(piles) == 1:
			return ceil(piles[0] / H)
		while lo <= hi:
			mid = (lo + hi) // 2
			count = sum(map(lambda x: ceil(x / mid), piles))
			if count > H:
				lo = mid + 1
			else:
				hi = mid - 1
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def useDays(pile, speed):
			days = pile // speed
			return days if pile % speed == 0 else days + 1

		def CanDone(piles, speed, H):
			numDays = 0
			for num in piles:
				numDays += useDays(num, speed)
			return numDays <= H
		maxEat = max(piles)
		(left, right) = (1, maxEat + 1)
		while left < right:
			mid = left + (right - left >> 1)
			if CanDone(piles, mid, H):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(lo, hi) = (1, max(piles))
		ans = hi
		while lo <= hi:
			k = (lo + hi) // 2
			time = 0
			for i in piles:
				t = int(ceil(i / k))
				if not t:
					t += 1
				time += t
			if time <= H:
				hi = k - 1
				ans = k
			else:
				lo = k + 1
		return ans


import math as m

class Solution:

	def check_time(piles, speed):
		hrs = 0
		for i in piles:
			hrs += int(m.ceil(i / speed))
		return hrs

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		low = 1
		high = float('-inf')
		for i in piles:
			high = max(high, i)
		if H == len(piles):
			return high
		while low <= high:
			mid = (low + high) // 2
			hrs = Solution.check_time(piles, mid)
			if hrs > H:
				low = mid + 1
			else:
				high = mid - 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		low = 1
		high = max(piles)

		def possible(k):
			time = 0
			for pile in piles:
				time += (pile - 1) // k + 1
			return time <= H
		while low <= high:
			mid = low + (high - low) // 2
			outcome = possible(mid)
			if possible(mid):
				high = mid - 1
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if len(piles) == H:
			return max(piles)
		low = 1
		high = max(piles)
		ans = high
		while low <= high:
			mid = (low + high) // 2
			h = H
			for i in range(len(piles)):
				if piles[i] <= mid:
					h -= 1
				elif piles[i] % mid == 0:
					h -= piles[i] // mid
				else:
					h -= piles[i] // mid + 1
			if h >= 0:
				ans = min(ans, mid)
				high = mid - 1
			else:
				low = mid + 1
		return ans


from math import ceil

class Solution:

	def ok(self, piles: List[int], k: int, H: int) -> bool:
		return sum([ceil(piles[i] / k) for i in range(len(piles))]) <= H

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		st = 1
		en = sum(piles)
		ans = en
		while st <= en:
			mid = st + (en - st) // 2
			if self.ok(piles, mid, H):
				ans = mid
				en = mid - 1
			else:
				st = mid + 1
		return ans


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		L = len(piles)
		if L == H:
			return max(piles)
		k2 = max(piles)
		k1 = 1
		res = k2
		k = k1
		while k1 < k2 - 1:
			cur = 0
			for j in range(L):
				cur += math.ceil(piles[j] / k)
				if cur > H:
					k1 = k
					break
			if cur <= H:
				k2 = k
				res = min(res, k)
			k = (k1 + k2) // 2
		return res


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def time(val):
			t = len(piles)
			for pile in piles:
				t += (pile - 1) // val
			return t
		(l, r) = (1, max(piles))
		while l <= r:
			mid = l + (r - l) // 2
			t = time(mid)
			if t <= H:
				r = mid - 1
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles, H):
		speed = math.floor(sum(piles) / H)
		while True:
			time = sum([math.ceil(x / speed) if speed else float('inf') for x in piles])
			print(f'speed={speed!r}, time={time!r}, H={H!r}')
			if time <= H:
				break
			speed += 1
		return speed


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		self.store = {}
		l = 1
		r = max(piles)
		while l <= r:
			m = l + (r - l) // 2
			if self.calc_h(piles, m) > H:
				l = m + 1
			else:
				if m == 1 or self.calc_h(piles, m - 1) > H:
					return m
				r = m - 1

	def calc_h(self, piles, K):
		if K not in self.store:
			h = [p // K + (p % K > 0) for p in piles]
			self.store[K] = int(sum(h))
		return self.store[K]


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def condition(k) -> bool:
			count = 0
			for v in piles:
				count += int(math.ceil(v / k))
				if count > H:
					return False
			return True
		(left, right) = (1, max(piles))
		while left < right:
			mid = left + (right - left) // 2
			if condition(mid):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if not piles:
			return -1
		(low, high) = (1, sum(piles))

		def isPossible(piles, target, H):
			return sum((math.ceil(p / target) for p in piles)) <= H
		while low < high:
			mid = low + (high - low) // 2
			if isPossible(piles, mid, H):
				high = mid
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while left < right:
			mid = (left + right) // 2
			if self.get_total_days(piles, mid) > H:
				left = mid + 1
			else:
				right = mid
		return left

	def get_total_days(self, piles: List[int], num_eat: int) -> int:
		if num_eat == 0:
			return 0
		total_days = 0
		for pile in piles:
			total_days += math.ceil(float(pile) / num_eat)
		return total_days


class Solution:

	def minEatingSpeed(self, array: List[int], hour: int) -> int:
		if len(array) == hour:
			return max(array)
		low = 1
		high = max(array)
		ans = high
		while low <= high:
			mid = (low + high) // 2
			h = hour
			for i in range(len(array)):
				if array[i] <= mid:
					h -= 1
				elif array[i] % mid == 0:
					h -= array[i] // mid
				else:
					h -= array[i] // mid + 1
				if h < 0:
					break
			if h >= 0:
				ans = mid
				high = mid - 1
			else:
				low = mid + 1
		return ans


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(K):
			return sum(((p - 1) // K + 1 for p in piles)) <= H
		(lo, hi) = (1, max(piles))
		while lo < hi:
			mi = (lo + hi) // 2
			if not possible(mi):
				lo = mi + 1
			else:
				hi = mi
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		maxB = max(piles)

		def getH(k):
			if not k:
				return float('inf')
			numHours = 0
			for pile in piles:
				numHours += pile // k + int(bool(pile % k))
			return numHours

		def bs(start, end):
			if start > end:
				return float('inf')
			mid = (start + end + 1) // 2
			h = getH(mid)
			if h < H:
				if mid != start:
					return min(mid, bs(start, mid - 1))
			if h > H:
				return bs(mid + 1, end)
			if h == H:
				while getH(mid - 1) == H:
					mid -= 1
			return mid
		return bs(0, maxB)


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def time_needed(K):
			return sum((p // K + (1 if p % K else 0) for p in piles))
		lower = max(1, sum(piles) // H)
		upper = max(piles)
		while lower < upper:
			if time_needed(lower) <= H:
				return lower
			lower += 1
			mid = (lower + upper) // 2
			if time_needed(mid) <= H:
				upper = mid
			else:
				lower = mid + 1
		return lower


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		max_k = 0
		for value in piles:
			max_k = max(max_k, value)

		def possible(k):
			hours = 0
			for item in piles:
				hours += math.ceil(item / k)
				if hours > H:
					return False
			if hours <= H:
				return True
			return False

		def binary_search(low, high):
			mid = low + (high - low) // 2
			if possible(low):
				return low
			elif possible(mid):
				return binary_search(low, mid)
			else:
				return binary_search(mid + 1, high)

		def binary_search_iter(low, high):
			pass
		return binary_search(1, max_k)


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		(low, high) = (1, max(piles))
		while low + 1 < high:
			mid = low + (high - low) // 2
			used_hrs = self.calc_hours(piles, mid)
			if used_hrs > H:
				low = mid
			else:
				high = mid
		if self.calc_hours(piles, low) <= H:
			return low
		if self.calc_hours(piles, high) <= H:
			return high

	@staticmethod
	def calc_hours(piles, K):
		return int(sum((math.ceil(pile / float(K)) for pile in piles)))


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def compute_hours(piles, K):
			ret = 0
			for p in piles:
				ret += math.ceil(p / K)
			return ret
		lo = 1
		hi = sum(piles)
		while lo < hi:
			mid = lo + (hi - lo + 1) // 2
			val = compute_hours(piles, mid)
			if val <= H:
				hi = mid - 1
			else:
				lo = mid
		if compute_hours(piles, hi) <= H:
			return hi
		else:
			return hi + 1


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = 1
		hi = max(piles)
		while lo < hi:
			mid = (hi - lo) // 2 + lo
			if sum([math.ceil(i / mid) for i in piles]) > H:
				lo = mid + 1
			else:
				hi = mid
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lower_bound = 1
		upper_bound = sum(piles)
		while lower_bound < upper_bound:
			speed = (lower_bound + upper_bound) // 2
			if self.can_finish(piles, speed, H):
				upper_bound = speed
			else:
				lower_bound = speed + 1
		return upper_bound

	def can_finish(self, piles, speed, h):
		hours = 0
		for bananas in piles:
			hours += math.ceil(bananas / speed)
		return hours <= h


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		s = sum(piles)
		if H == n:
			return max(piles)
		if H > s:
			return 1
		k = s // H
		i = 0
		while True:
			t = 0
			for j in range(len(piles)):
				t += math.ceil(piles[j] / k)
			if t <= H:
				return k
			k += 1
		return 0


class Solution:

	def minEatingSpeed(self, piles, H):
		(lo, hi) = (1, max(piles))
		while lo <= hi:
			K = lo + (hi - lo >> 1)
			if self.countTimeEatAllAtSpeed(K, piles) <= H:
				hi = K - 1
			else:
				lo = K + 1
		return lo

	def countTimeEatAllAtSpeed(self, K, piles):
		countHours = 0
		for pile in piles:
			countHours += pile // K
			if pile % K != 0:
				countHours += 1
		return countHours


class Solution:

	def hours(self, piles, k):
		cnt = 0
		for p in piles:
			if p <= k:
				cnt = cnt + 1
			else:
				cnt = cnt + p // k + 1
		return cnt

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if len(piles) == 1:
			return 1 + piles[0] // H
		l = 0
		r = max(piles)
		while l <= r:
			mid = (l + r) // 2
			hrs = self.hours(piles, mid)
			if hrs <= H:
				ans = mid
				r = mid - 1
			else:
				l = mid + 1
		return ans


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while right > left:
			speed = int((left + right) / 2)
			total_hours = 0
			for i in piles:
				total_hours += math.ceil(i / speed)
			if total_hours > H:
				left = speed + 1
			else:
				right = speed
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = 1
		hi = max(piles)
		ans = 0
		while hi >= lo:
			mid = (lo + hi) // 2
			if self.check(mid, piles, H):
				ans = mid
				hi = mid - 1
			else:
				lo = mid + 1
		return ans

	def check(self, mid, piles, H):
		i = 0
		count = 0
		new = piles[:]
		while i < len(new):
			if count > H:
				return False
			if mid >= new[i]:
				count += 1
				i += 1
			else:
				count += new[i] // mid + 1
				i += 1
		if count > H:
			return False
		return True


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if H == len(piles):
			return max(piles)
		l = 1
		r = max(piles) + 1
		while l < r:
			m = l + (r - l) // 2
			if self.minHours(piles, m) <= H:
				r = m
			elif self.minHours(piles, m) > H:
				l = m + 1
		return l

	def minHours(self, piles, k):
		h = 0
		for p in piles:
			if p % k == 0:
				h += p // k
			else:
				h = h + p // k + 1
		return h


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		min_speed = 1
		max_speed = sorted(piles)[-1]
		while min_speed <= max_speed:
			pivot = min_speed + (max_speed - min_speed) // 2
			hours = [math.ceil(x / pivot) for x in piles]
			r = 0
			for x in hours:
				if x == 0:
					r += 1
				else:
					r += x
			if r == H:
				return pivot
			elif min_speed == max_speed and r >= H:
				return pivot + 1
			elif r < H:
				max_speed = pivot - 1
			elif r > H:
				min_speed = pivot + 1
		return pivot


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def cnt(k, piles):
			ans = 0
			for p in piles:
				ans += math.ceil(p / float(k))
			return int(ans)
		piles.sort()
		l = 1
		h = piles[-1]
		mid = (l + h) // 2
		while l <= h:
			s = cnt(mid, piles)
			if s <= H:
				h = mid - 1
			else:
				l = mid + 1
			mid = (l + h) // 2
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def valid(mid):
			if mid == 0:
				return False
			hours = 0
			for i in piles:
				if i < mid:
					hours += 1
				else:
					hours += math.ceil(i / mid)
			return hours <= H
		if not piles:
			return 0
		piles = sorted(piles)
		(s, e) = (0, sum(piles))
		ans = -1
		while s <= e:
			mid = (s + e) // 2
			if valid(mid):
				ans = mid
				e = mid - 1
			else:
				s = mid + 1
		return ans


class Solution:

	def get_hours(self, piles, k):
		ans = 0
		for x in piles:
			if x % k == 0:
				ans += x // k
			else:
				ans += int(x // k) + 1
		return ans

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(n, max_val) = (len(piles), max(piles))
		if H < n:
			return 1 << 31
		(start, end) = (1, max_val)
		while start <= end:
			mid = (end - start) // 2 + start
			h = self.get_hours(piles, mid)
			if h <= H:
				end = mid - 1
			else:
				start = mid + 1
		return start if start <= max_val else start - 1


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def is_smaller_equal_H(piles, K, H):
			ret = 0
			for p in piles:
				ret += math.ceil(p / K)
				if ret > H:
					return False
			return True
		lo = 1
		hi = sum(piles)
		while lo < hi:
			mid = lo + (hi - lo + 1) // 2
			flag = is_smaller_equal_H(piles, mid, H)
			if flag:
				hi = mid - 1
			else:
				lo = mid
		if is_smaller_equal_H(piles, hi, H):
			return hi
		else:
			return hi + 1


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def isValid(mid):
			hours = 0
			for banana in piles:
				div = math.ceil(banana / mid)
				hours += div
				if hours > H:
					return False
			return True

		def binsearch():
			low = 1
			high = sum(piles)
			while low < high:
				mid = low + (high - low) // 2
				if isValid(mid):
					high = mid
				else:
					low = mid + 1
			return low
		total = sum(piles)
		return binsearch()


from typing import List
from math import ceil

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def get_hours(piles, K):
			total = 0
			for num in piles:
				total += ceil(num / K)
			return total
		(left, right) = (1, max(piles))
		while left < right:
			mid = left + (right - left) // 2
			if get_hours(piles, mid) > H:
				left = mid + 1
			else:
				right = mid
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def feasible(bananas):
			hour = 0
			for pile in piles:
				(hs, left) = divmod(pile, bananas)
				hour += hs + (left > 0)
			return hour <= H
		l = 1
		r = sum(piles)
		while l < r:
			mid = l + r >> 1
			if feasible(mid):
				r = mid
			else:
				l = mid + 1
		return l


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(start, end) = (1, max(piles))
		while start + 1 < end:
			mid = (start + end) // 2
			if self.is_feasible(piles, H, mid) == False:
				start = mid + 1
			elif self.is_feasible(piles, H, mid) == True:
				end = mid
		if self.is_feasible(piles, H, start):
			return start
		else:
			return end

	def is_feasible(self, piles, H, speed):
		res = 0
		for i in piles:
			res += math.ceil(i / speed)
		if res <= H:
			return True
		else:
			return False


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = int(math.ceil(sum(piles) / H))
		hi = sum(piles)
		hours = lambda j: sum([int(math.ceil(i / j)) for i in piles])
		out = -1
		while lo <= hi:
			mid = (lo + hi) // 2
			res = hours(mid)
			if res <= H:
				out = mid
			if res <= H:
				hi = mid - 1
			else:
				lo = mid + 1
		return out


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		low = 1
		ans = [0]
		high = max(piles)
		h = [H]

		def check(speed, piles):
			cost = 0
			for i in piles:
				cost += math.ceil(i / speed)
				if cost > h[0]:
					return False
			return True

		def binary(low, high):
			if low > high:
				return high
			mid = (low + high) // 2
			if check(mid, piles):
				ans[0] = mid
				binary(low, mid - 1)
			else:
				binary(mid + 1, high)
		binary(low, high)
		return ans[-1]


from math import ceil

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def doesViolate(mid):
			requiredHour = 0
			for i in range(0, len(piles)):
				if mid > piles[i]:
					requiredHour += 1
				else:
					requiredHour += math.ceil(piles[i] / mid)
			if requiredHour > H:
				return True
			else:
				return False
		low = 1
		high = max(piles)
		while low < high:
			mid = (low + high) // 2
			if doesViolate(mid) == True:
				low = mid + 1
			else:
				high = mid
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		from math import ceil
		left = 1
		right = max(piles) + 1
		timeConsumption = lambda speed: sum((ceil(pile / speed) for pile in piles))
		while left < right:
			mid = left + (right - left) // 2
			time = timeConsumption(mid)
			if time > H:
				left = mid + 1
			else:
				right = mid
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		l = max(sum(piles) // H, 1)
		h = max(piles)
		while l < h:
			mid = (l + h) // 2
			timeL = self.timeTaken(piles, l)
			timeMid = self.timeTaken(piles, mid)
			if timeL <= H:
				return l
			elif timeMid <= H:
				h = mid
				timeH = timeMid
				l += 1
			else:
				l = mid + 1
		return l

	def timeTaken(self, piles, n):
		summ = 0
		for v in piles:
			summ += v // n
			if v % n:
				summ += 1
		return summ


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if H == len(piles):
			return max(piles)
		elif sum(piles) <= H:
			return 1
		cntr = collections.Counter(piles)
		lst = set()
		for key in cntr.keys():
			lst.add((key, cntr[key]))
		s = 2
		e = max(piles) - 1
		while s <= e:
			K = int((s + e) / 2)
			total = 0
			for (pile, n) in lst:
				(q, r) = divmod(pile, K)
				if r:
					total += (q + 1) * n
				else:
					total += q * n
				if total > H:
					break
			if total <= H:
				e = K - 1
			else:
				s = K + 1
		return s


from math import ceil

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		hi_fail = 0
		low_pass = max(piles)
		if len(piles) == H:
			return low_pass
		piles.sort(reverse=True)
		speed = low_pass // 2
		while low_pass - hi_fail > 1:
			for (i, num_bananas) in enumerate(piles):
				if num_bananas <= speed:
					break
			else:
				i += 1
			if not self.can_eat_all(piles, H, speed, i):
				hi_fail = speed
			else:
				low_pass = speed
			speed = (low_pass + hi_fail) // 2
		return low_pass

	def can_eat_all(self, piles, hours, speed, stop_ind):
		extra_hours = hours - len(piles)
		for i in range(stop_ind):
			hours_needed = int(ceil(piles[i] / speed))
			extra_hours -= hours_needed - 1
			if extra_hours < 0:
				return False
		if len(piles) == 1 and extra_hours == 0:
			return False
		return True


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while left + 1 < right:
			mid = left + (right - left) // 2
			if self.possible(piles, H, mid):
				right = mid
			else:
				left = mid
		if self.possible(piles, H, left):
			return left
		return right

	def possible(self, piles, H, K):
		time = 0
		for p in piles:
			time += math.ceil(p / K)
		return time <= H


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def finishable(piles, H, eatRate) -> bool:
			numHours = 0
			for pile in piles:
				numHours += ceil(pile / eatRate)
			return numHours <= H
		(left, right) = (1, max(piles))
		while left < right:
			mid = left + (right - left) // 2
			if finishable(piles, H, mid):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		right = 10 ** 9
		left = 1
		piles.sort()
		while left + 1 < right:
			mid = (left + right) // 2
			if self.canEatAll(piles, mid, H):
				right = mid
			else:
				left = mid
		return left if self.canEatAll(piles, left, H) else right

	def canEatAll(self, piles, speed, H):
		res = 0
		for pile in piles:
			res += (pile - 1) // speed + 1
		return res <= H


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(s, e) = (1, max(piles))
		minK = float('inf')
		while s <= e:
			m = (s + e) // 2
			if self.eat(piles, m) > H:
				s = m + 1
			else:
				minK = min(minK, m)
				e = m - 1
		return minK

	def eat(self, piles, K):
		ret = 0
		for p in piles:
			ret += math.ceil(p / K)
		return ret


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if len(piles) == 1:
			(div, rem) = divmod(piles[0], H)
			if rem == 0:
				return div
			else:
				return div + 1
		left = 0
		right = sum(piles)
		while left < right:
			mid = (left + right) // 2
			if self.CalcTime(piles, mid, H):
				right = mid
			else:
				left = mid + 1
		return left

	def CalcTime(self, piles, K, H):
		h = 0
		for p in piles:
			(div, rem) = divmod(p, K)
			h += div
			if rem > 0:
				h += 1
			if h > H:
				return False
		return h <= H


class Solution:

	def time_taken(self, piles, n):
		return sum((v // n + (1 if v % n else 0) for v in piles))

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = max(1, sum(piles) // H)
		hi = max(piles)
		t_hi = self.time_taken(piles, hi)
		while lo < hi:
			mid = (lo + hi) // 2
			t_lo = self.time_taken(piles, lo)
			t_mid = self.time_taken(piles, mid)
			if t_lo <= H:
				return lo
			elif t_mid <= H:
				(hi, t_hi) = (mid, t_mid)
				lo += 1
			else:
				lo = mid + 1
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def ifeatK(k):
			hour = 0
			for pile in piles:
				hour += math.ceil(pile / k)
			return hour
		start = 1
		end = sum(piles)
		while start + 1 < end:
			mid = (start + end) // 2
			if ifeatK(mid) < H:
				end = mid
			elif ifeatK(mid) > H:
				start = mid
			else:
				end = mid
		if ifeatK(start) > H:
			return end
		if ifeatK(start) == H:
			return start
		if ifeatK(end) == H:
			return end
		return start


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		N = len(piles)
		start = 1
		end = max(piles)
		while start + 1 < end:
			mid = start + (end - start) // 2
			if self._can_complete(piles, mid, H):
				end = mid
			else:
				start = mid
		if self._can_complete(piles, start, H):
			return start
		else:
			return end

	def _can_complete(self, piles, K, H):
		i = 0
		N = len(piles)
		c = 0
		for d in piles:
			c += math.ceil(d / K)
		return c <= H


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def sop(A, H, K):
			if K == 0:
				return False
			count = 0
			for i in A:
				if i % K == 0:
					count += i // K
				else:
					count += i // K + 1
			if count <= H:
				return True
			return False
		l = sum(piles) // H
		r = max(piles)
		print((l, r))
		print(sop(piles, H, l))
		if len(piles) == 1:
			return l + 1
		m = (l + r) // 2
		while l <= r:
			if sop(piles, H, l) == False and sop(piles, H, l + 1) == True:
				return l + 1
			if sop(piles, H, r - 1) == False and sop(piles, H, r) == True:
				return r
			if sop(piles, H, m) == False:
				l = m
				m = (l + r) // 2
			else:
				r = m
				m = (l + r) // 2


class Solution:

	def canEat(self, piles, bananas, H):
		cur_H = 0
		for pile in piles:
			if pile % bananas == 0:
				cur_H += pile // bananas
			else:
				cur_H += pile // bananas + 1
		if cur_H > H:
			return False
		return True

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		min_speed = 1
		max_speed = max(piles)
		while min_speed < max_speed:
			mid = (min_speed + max_speed) // 2
			if self.canEat(piles, mid, H):
				max_speed = mid
			else:
				min_speed = mid + 1
		return min_speed


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(l, r) = (1, max(piles))
		while l <= r:
			m = l + (r - l) // 2
			if self.speedBalancer(piles, m) > H:
				l = m + 1
			elif self.speedBalancer(piles, m) <= H:
				r = m - 1
		return l

	def speedBalancer(self, piles, target):
		h = 0
		for i in piles:
			h += i // target
			if i % target != 0:
				h += 1
		return h


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def condition(arr, k, h):
			res = 0
			for i in arr:
				res += math.ceil(i / k)
			if res <= h:
				return True
			return False
		(l, r) = (1, max(piles))
		while l < r:
			m = l + (r - l) // 2
			if condition(piles, m, H):
				r = m
			else:
				l = m + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		if n >= H:
			return max(piles)

		def check(m):
			ret = 0
			for p in piles:
				ret += p // m + (p % m != 0)
			return ret
		upper = max(piles)
		(lo, hi) = (1, upper)
		while lo <= hi:
			mid = (lo + hi) // 2
			if check(mid) <= H:
				hi = mid - 1
			else:
				lo = mid + 1
		return lo


import math

class Solution:

	def cc(self, l, n):
		ans = 0
		for i in l:
			ans += math.ceil(i / n)
		return ans

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		if H == n:
			return max(piles)
		else:
			l = math.ceil(sum(piles) / H) - 1
			r = max(piles) + 1
			while r - l > 1:
				pivot = (l + r) // 2
				if self.cc(piles, pivot) <= H:
					r = pivot
				elif self.cc(piles, pivot) > H:
					l = pivot
			return r


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		piles.sort()
		(l, r) = (1, max(piles))
		while l <= r:
			m = (l + r) // 2
			if sum([(x - 1) // m + 1 for x in piles]) > H:
				l = m + 1
			elif sum([math.ceil(x / m) for x in piles]) < H:
				r = m - 1
			else:
				return m
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		l = 1
		r = max(piles)
		while l < r:
			m = l + (r - l) // 2
			h = 0
			for i in piles:
				h += math.ceil(i / m)
			if h > H:
				l = m + 1
			else:
				r = m
		return l


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def feasible(maxBananas):
			hours = 0
			for pile in piles:
				hours += math.ceil(pile / maxBananas)
				if hours > H:
					return False
			return True
		left = 1
		right = max(piles)
		while left < right:
			mid = left + (right - left) // 2
			if feasible(mid):
				right = mid
			else:
				left = mid + 1
		return left


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		le = 1
		ri = sum(piles)

		def checkHours(speed):
			s = 0
			for item in piles:
				s += math.ceil(item / speed)
			return s
		while le + 1 < ri:
			mid = le + (ri - le) // 2
			result = checkHours(mid)
			if result <= H:
				ri = mid
			else:
				le = mid
		result = checkHours(le)
		if result <= H:
			return le
		else:
			return ri


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while left < right:
			mid = (left + right) // 2
			hours = 0
			s = i = 0
			rem = 0
			while i < len(piles):
				hours += int(math.ceil(piles[i] / mid))
				i += 1
			if hours <= H:
				right = mid
			else:
				left = mid + 1
		return left


from math import ceil

def count_hr(piles, k):
	return sum([ceil(p / k) for p in piles])

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if len(piles) > H:
			return
		(lo, hi) = (1, max(piles))
		while lo <= hi:
			mid = (lo + hi) // 2
			if count_hr(piles, mid) > H:
				lo = mid + 1
			elif count_hr(piles, mid) <= H:
				hi = mid - 1
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def is_feasible(rate, H, piles):
			count = 0
			for i in range(len(piles)):
				count += piles[i] // rate
				if piles[i] % rate != 0:
					count += 1
				if count > H:
					return False
			return True
		l = 1
		h = sum(piles)
		ans = float('inf')
		while l <= h:
			mid = (l + h) // 2
			if is_feasible(mid, H, piles):
				ans = min(ans, mid)
				h = mid - 1
			else:
				l = mid + 1
		return ans


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		ceiling = lambda x, y: (x + y - 1) // y

		def timeTaken(v):
			totalTime = 0
			for p in piles:
				totalTime += ceiling(p, v)
			return totalTime

		def binarySearch(s, e, up_bound):
			if s == e:
				return s
			m = (s + e) // 2
			if timeTaken(m) <= up_bound:
				return binarySearch(s, m, up_bound)
			else:
				return binarySearch(m + 1, e, up_bound)
		pmax = 1
		for p in piles:
			pmax = max(pmax, p)
		return binarySearch(1, pmax, H)


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def is_valid(speed):
			curr = 0
			for n in piles:
				(q, r) = divmod(n, speed)
				if r:
					q += 1
				curr += q
				if curr > H:
					return False
			return True
		(l, r) = (1, max(piles))
		res = -1
		while l <= r:
			m = l + (r - l) // 2
			if is_valid(m):
				res = m
				r = m - 1
			else:
				l = m + 1
		return res


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(K):
			return sum((math.ceil(p / K) for p in piles)) <= H
		low = 1
		high = max(piles) + 1
		while low < high:
			mid = low + (high - low) // 2
			if possible(mid):
				high = mid
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def can_finish(k):
			h = 0
			for p in piles:
				(d, r) = divmod(p, k)
				if r:
					d += 1
				h += d
			return h <= H
		l = 1
		r = max(piles)
		while l < r:
			m = (l + r) // 2
			if can_finish(m):
				r = m
			else:
				l = m + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def is_ok(piles, H, mid):
			sum = 0
			for i in range(len(piles)):
				if piles[i] <= mid:
					sum += 1
				else:
					sum += math.ceil(piles[i] / mid)
			return sum <= H
		ok = sum(piles)
		ng = 0
		while abs(ok - ng) > 1:
			mid = (ok + ng) // 2
			if is_ok(piles, H, mid):
				ok = mid
			else:
				ng = mid
		return ok


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(lo, hi) = (1, 1000000001)
		ans = -1
		N = len(piles)

		def poss(val):
			cnt = 0
			for n in range(N):
				cnt += math.ceil(piles[n] / val)
			if cnt <= H:
				return True
			return False
		while lo <= hi:
			mid = lo + (hi - lo) // 2
			if poss(mid):
				ans = mid
				hi = mid - 1
			else:
				lo = mid + 1
		return ans


class Solution:

	def minEatingSpeed(self, piles, H):
		start = sum(piles) // H + 1
		while start <= max(piles):
			suplus = sum(map(lambda x: (start - x % start) % start, piles))
			if suplus + sum(piles) <= start * H:
				return start
			else:
				start += 1
		return max(piles)


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def time(val):
			t = len(piles)
			for pile in piles:
				t += (pile - 1) // val
			return t
		s = sum(piles)
		(l, r) = (math.ceil(s / H), math.ceil(s / (H - len(piles) + 1)))
		while l <= r:
			mid = l + (r - l) // 2
			t = time(mid)
			if t <= H:
				r = mid - 1
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		l = max(1, sum(piles) // H)
		r = max(piles) // (H // len(piles)) + 1

		def hours(rate):
			count = 0
			for x in piles:
				count += (x + rate - 1) // rate
			return count
		while l <= r:
			mid = (l + r) // 2
			h = hours(mid)
			if h > H:
				l = mid + 1
			else:
				ans = mid
				r = mid - 1
		return ans


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if len(piles) == 1:
			return piles[0] // H if piles[0] % H == 0 else piles[0] // H + 1
		l = sum(piles) // H
		h = max(piles) * len(piles) // H + 1

		def feasible(k):
			return sum(((p - 1) // k + 1 for p in piles)) <= H
		while l < h:
			mid = (l + h) // 2
			if feasible(mid):
				h = mid
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lenth = len(piles)
		s = (min(piles) - 1) * lenth // H + 1
		m = (max(piles) - 1) * lenth // H + 1
		if int(m) < m:
			m = int(m) + 1
		if s == m:
			return s
		while s < m:
			mid = (s + m) // 2
			count = sum([(i - 1) // mid + 1 for i in piles])
			if count > H:
				s = mid + 1
			else:
				m = mid
		return s


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		k = sum(piles) // H
		if k == 0:
			return 1
		while True:
			h = 0
			prev = k
			for p in piles:
				print(p, k)
				if p > 1:
					h += (p - 1) // k + 1
				else:
					h += 1
				if h > H:
					break
			if h <= H:
				return k
			k += 1


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(K):
			return sum((ceil(pile / K) for pile in piles)) <= H
		total = sum(piles)
		(lo, hi) = (ceil(total / H), ceil(total / (H - len(piles) + 1)))
		while lo < hi:
			mid = lo + (hi - lo) // 2
			if possible(mid):
				hi = mid
			else:
				lo = mid + 1
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		piles.sort()

		def finish(k):
			return sum(((p - 1) // k + 1 for p in piles)) <= H
		r = 0
		while r < n:
			if finish(piles[r]):
				break
			else:
				r += 1
		start = 1 if r == 0 else piles[0]
		end = piles[r]
		while start < end:
			mid = (start + end) // 2
			if finish(mid):
				end = mid
			else:
				start = mid + 1
		return start


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if not piles:
			return 0
		(l, r) = (1, max(piles))

		def canDo(pace):
			ans = 0
			for v in piles:
				ans -= -v // pace
			return ans <= H
		while l < r:
			m = (l + r) // 2
			if canDo(m):
				r = m
			else:
				l = m + 1
		return l


class Solution:

	def minEatingSpeed(self, piles, H):
		import math
		left = 1
		right = math.ceil(max(piles) * len(piles) / H)
		while left < right:
			mid = left + (right - left) // 2
			if self.f(piles, mid) > H:
				left = mid + 1
			else:
				right = mid
		return left

	def f(self, piles, K):
		import math
		hours = 0
		for pile in piles:
			hours += math.ceil(pile / K)
		return hours


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(l, r) = (1, max(piles))
		while l < r:
			mid = l + (r - l) // 2
			if sum([-pile // mid for pile in piles]) < -H:
				l = mid + 1
			else:
				r = mid
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def feasible(speed) -> bool:
			return sum(((pile - 1) // speed + 1 for pile in piles)) <= H
		(left, right) = (1, max(piles))
		while left < right:
			mid = left + (right - left) // 2
			if feasible(mid):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while left <= right:
			mid = (left + right) // 2
			hours = sum(((x - 1) // mid + 1 for x in piles))
			if hours <= H:
				right = mid - 1
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		mini = 1
		maxi = max(piles)
		ans = 0
		while mini <= maxi:
			mid = mini + (maxi - mini) // 2
			value = sum(((p - 1) // mid + 1 for p in piles))
			if value <= H:
				ans = mid
				maxi = mid - 1
			else:
				mini = mid + 1
		return ans


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(k):
			return sum(((num - 1) // k + 1 for num in piles)) <= H
		(left, right) = (1, max(piles))
		while left < right:
			mid = (left + right) // 2
			if not possible(mid):
				left = mid + 1
			else:
				right = mid
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(l, r) = (1, max(piles))
		while l < r:
			m = (l + r) // 2
			if sum(((p + m - 1) // m for p in piles)) > H:
				l = m + 1
			else:
				r = m
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(low, high) = (1, max(piles))
		while low < high:
			K = low + (high - low) // 2
			h = sum([(pile - 1) // K + 1 for pile in piles])
			if h <= H:
				high = K
			else:
				low = K + 1
		return low


from math import ceil

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(left, right) = (1, max(piles))

		def banana_test(bans):
			return sum([ceil(pile / bans) for pile in piles]) <= H
		while left < right:
			mid = left + (right - left) // 2
			if banana_test(mid):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def eats(piles, h, k):
			hours = 0
			for pile in piles:
				hours += (pile - 1) // k + 1
			return hours <= h
		lo = 1
		hi = 10 ** 9
		while lo < hi:
			mid = lo + (hi - lo) // 2
			if eats(piles, H, mid):
				hi = mid
			else:
				lo = mid + 1
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)

		def can(k):
			return sum(((p - 1) // k + 1 for p in piles)) <= H
		while left < right:
			mid = (left + right) // 2
			if can(mid):
				right = mid
			else:
				left = mid + 1
		return right


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(lo, hi) = (1, max(piles))
		while lo < hi:
			mid = (lo + hi) // 2
			(cur_cap, num_hrs) = (0, 0)
			for p in piles:
				cur_cap = p
				if cur_cap <= mid:
					num_hrs += 1
				else:
					num_hrs += cur_cap // mid + 1
			if num_hrs > H:
				lo = mid + 1
			else:
				hi = mid
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def simulate(k):
			hours = 0
			for pile in piles:
				hours += ceil(pile / k)
			return hours
		lower = 1
		upper = 1
		for pile in piles:
			upper = max(upper, pile)
		while lower < upper:
			midpoint = (upper + lower) // 2
			if simulate(midpoint) > H:
				lower = midpoint + 1
			else:
				upper = midpoint
		return upper


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(K):
			return sum((math.ceil(p / K) for p in piles)) <= H
		N = len(piles)
		if H == N:
			return max(piles)
		sm = sum(piles)
		(lo, hi) = (int(sm / H) + 1, math.ceil(sm / (H - N)))
		while lo < hi:
			mi = (lo + hi) // 2
			if not possible(mi):
				lo = mi + 1
			else:
				hi = mi
		return hi


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(l, h) = (1, max(piles))

		def canFinish(k):
			hoursTaken = sum([ceil(p / k) for p in piles])
			return hoursTaken <= H
		while l < h:
			mid = l + (h - l) // 2
			if canFinish(mid):
				h = mid
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def can_eat(x: int, h: int) -> bool:
			hrs = 0
			for p in piles:
				if p <= x:
					hrs += 1
				else:
					hrs += p // x + 1
				if hrs > h:
					return False
			return True
		(low, high) = (1, max(piles))
		while low < high:
			mid = low + (high - low) // 2
			if can_eat(mid, H):
				high = mid
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def count(k):
			hours = 0
			for i in range(len(piles)):
				hours += (piles[i] + k - 1) // k
			return hours
		l = 1
		r = 1000000000
		while l < r:
			m = l + (r - l) // 2
			if count(m) > H:
				l = m + 1
			else:
				r = m
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(K):
			count = 0
			for banana in piles:
				if banana % K == 0:
					count += banana / K
				else:
					count += banana // K + 1
			if count <= H:
				return True
			else:
				return False
		(left, right) = (1, max(piles))
		while left <= right:
			mid = (left + right) // 2
			if possible(mid):
				right = mid - 1
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def eat_speed(K, H):
			banana_per_hour = 0
			for pile in piles:
				banana_per_hour += pile // K
				if pile % K != 0:
					banana_per_hour += 1
			return banana_per_hour
		left = 1
		right = max(piles)
		while left <= right:
			K = left + (right - left) // 2
			banana_per_hour = eat_speed(K, H)
			if banana_per_hour <= H:
				right = K - 1
			else:
				left = K + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		l = 1
		r = max(piles)

		def findTime(count):
			hr = 0
			for p in piles:
				hr += (p - 1) // count + 1
				if hr > H:
					return False
			return True
		while l < r:
			mid = l + (r - l) // 2
			if findTime(mid):
				r = mid
			else:
				l = mid + 1
		return l


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def count_hours(k):
			hours = 0
			if k == 1:
				return sum(piles)
			for p in piles:
				hours += p // k
				if p % k != 0:
					hours += 1
			return hours
		least = 1
		most = max(piles)
		while least <= most:
			mid = (most + least) // 2
			num_hours = count_hours(mid)
			if num_hours <= H:
				most = mid - 1
			else:
				least = mid + 1
		return least


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(left, right) = (1, max(piles))
		while left < right:
			mid = left + (right - left) // 2
			if self.__getEatHours(piles, mid) <= H:
				right = mid
			else:
				left = mid + 1
		return left

	def __getEatHours(self, piles, speed):
		hours = 0
		for p in piles:
			hours += p // speed
			if p % speed != 0:
				hours += 1
		return hours


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(left, right) = (1, max(piles))
		while left <= right:
			k = left + (right - left) // 2
			if self.finish(k, piles) <= H:
				right = k - 1
			else:
				left = k + 1
		return left

	def finish(self, k, piles):
		res = 0
		for pile in piles:
			res += pile // k
			if pile % k != 0:
				res += 1
		return res


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def get_hours_needed(piles, K):
			hours_needed = 0
			for pile in piles:
				hours_needed += pile // K
				if pile % K != 0:
					hours_needed += 1
			return hours_needed
		lo = 1
		hi = max(piles)
		while lo < hi:
			mid = lo + (hi - lo) // 2
			if get_hours_needed(piles, mid) > H:
				lo = mid + 1
			else:
				hi = mid
		return lo


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		maxPile = 0
		for i in piles:
			if i > maxPile:
				maxPile = i
		low = 1
		high = maxPile
		minVal = maxPile
		while low <= high:
			middle = (low + high) // 2
			numHours = 0
			for j in piles:
				numHours += j // middle
				if j % middle > 0:
					numHours += 1
			if numHours <= H:
				minVal = middle
				high = middle - 1
			else:
				low = middle + 1
		return minVal


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		if not n:
			return -1

		def binary_search(l, r):
			nonlocal piles, H
			while l < r:
				mid = (l + r) // 2
				if num_hours(mid) <= H:
					r = mid
				else:
					l = mid + 1
			return l

		def num_hours(bananas_per_hour):
			nonlocal piles
			res = 0
			for i in piles:
				if bananas_per_hour >= i:
					res += 1
					continue
				res += i // bananas_per_hour
				res += 1 if i % bananas_per_hour else 0
			return res
		return binary_search(1, max(piles))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def helper(speed):
			h = 0
			for p in piles:
				h += math.ceil(p / speed)
			return h
		if not piles or len(piles) == 0:
			return 0
		(start, end) = (1, max(piles))
		while start + 1 < end:
			mid = start + (end - start) // 2
			h = helper(mid)
			if h <= H:
				end = mid
			else:
				start = mid
		return start if helper(start) <= H else end


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def possible(x):
			if x == 0:
				return False
			h = 0
			for i in piles:
				h += math.ceil(i / x)
			return h <= H
		high = max(piles)
		low = 1
		while low < high:
			mid = low + (high - low) // 2
			if possible(mid):
				high = mid
			else:
				low = mid + 1
		return low


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = math.ceil(sum(piles) / H)
		right = max(piles)
		while left <= right:
			middle = (left + right) // 2
			if is_valid(piles, H, middle):
				right = middle - 1
			else:
				left = middle + 1
		return left

def is_valid(piles, H, speed):
	hour = 0
	for pile in piles:
		hour += math.ceil(pile / speed)
	return hour <= H


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		if H == len(piles):
			return max(piles)
		else:
			if sum(piles) % H == 0:
				tempMin = sum(piles) // H
			else:
				tempMin = sum(piles) // H + 1
			tempMax = max(piles)
			while tempMin != tempMax:
				tempMid = (tempMax - tempMin) // 2 + tempMin
				if self.ifOk(piles, H, tempMid):
					tempMax = tempMid
				else:
					tempMin = tempMid + 1
			return tempMin

	def ifOk(self, piles, H, K):
		hourNeed = 0
		for pile in piles:
			if pile % K == 0:
				hourNeed = hourNeed + pile // K
			else:
				hourNeed = hourNeed + pile // K + 1
			if hourNeed > H:
				return False
		return True


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def canEatAllBananas(speed):
			count = 0
			for pile in piles:
				if pile >= speed:
					count += pile // speed
				if pile % speed != 0:
					count += 1
			return count <= H
		low = 1
		high = max(piles)
		while low <= high:
			mid = low + (high - low) // 2
			if canEatAllBananas(mid):
				high = mid - 1
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def eatingPossible(cap, piles, H):
			h = 0
			for pile in piles:
				h += pile // cap
				if pile % cap != 0:
					h += 1
				if h > H:
					return False
			return True
		piles.sort()
		left = 1
		right = max(piles)
		while left < right:
			mid = left + (right - left) // 2
			if eatingPossible(mid, piles, H):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def isValid(k):
			total = 0
			for pile in piles:
				total += math.ceil(pile / k)
			return total <= H
		(i, j) = (1, max(piles))
		while i < j:
			mid = i + (j - i) // 2
			if isValid(mid):
				j = mid
			else:
				i = mid + 1
		return i


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:

		def feasible(threshold):
			count = 0
			for pile in piles:
				count += math.ceil(pile / threshold)
				if count > H:
					return False
			return True
		left = 1
		right = max(piles)
		while left < right:
			mid = left + (right - left >> 1)
			if feasible(mid):
				right = mid
			else:
				left = mid + 1
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		min_speed = 1
		max_speed = max(piles)
		while min_speed <= max_speed:
			pivot = min_speed + (max_speed - min_speed) // 2
			r = sum([math.ceil(x / pivot) for x in piles])
			if r == H:
				return pivot
			elif min_speed == max_speed and r >= H:
				return pivot + 1
			elif r < H:
				max_speed = pivot - 1
			elif r > H:
				min_speed = pivot + 1
		return pivot


import math

class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		left = 1
		right = max(piles)
		while left < right:
			K = (left + right) // 2
			hours = 0
			for pile in piles:
				if pile <= K:
					hours += 1
				else:
					hours += math.ceil(pile / K)
			if hours > H:
				left = K + 1
			else:
				right = K
		return left


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		(low, high) = (1, max(piles))

		def isPossible(eatRate):
			total = 0
			for numBanana in piles:
				total += (numBanana - 1) // eatRate + 1
			return total <= H
		while low < high:
			mid = (low + high) // 2
			if isPossible(mid):
				high = mid
			else:
				low = mid + 1
		return low


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		n = len(piles)
		if not n:
			return -1

		def binary_search(l, r):
			nonlocal piles, H
			while l < r:
				mid = (l + r) // 2
				if num_hours(mid) <= H:
					r = mid
				else:
					l = mid + 1
			return l

		def num_hours(k):
			nonlocal n, piles
			res = 0
			for i in range(n):
				num = piles[i]
				if k >= num:
					res += 1
					continue
				res += num // k
				res += 1 if num % k else 0
			return res
		return binary_search(1, max(piles))


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		minK = 1
		maxK = 0
		for pile in piles:
			if pile > maxK:
				maxK = pile
		low = minK
		high = maxK
		mid = (low + high) // 2
		while low < high:
			testK = mid
			if self.validK(piles, H, mid):
				high = mid
			else:
				low = mid + 1
			mid = (low + high) // 2
		return high

	def validK(self, piles, H, eatspeed):
		hourCount = 0
		for pile in piles:
			hoursUsed = ceil(pile / eatspeed)
			hourCount += hoursUsed
			if hourCount > H:
				return False
		return True


class Solution:

	def minEatingSpeed(self, piles: List[int], H: int) -> int:
		lo = 1
		hi = max(piles)

		def ok(K):
			return sum((1 + (pile - 1) // K for pile in piles)) <= H
		while lo < hi:
			mid = (lo + hi) // 2
			if ok(mid):
				hi = mid
			else:
				lo = mid + 1
		return lo