分石子问题
题解源自:牛客大佬——745599318
思路:
#令res表示分裂后m堆的最小值,
#res一定在[1, min{a[i], i=0,1...,n-1}]区间内,记左右区间分别为left, right。
#mid初始值去区间中值,即mid=left+(right-left)/2,利用二分思想不断找到mid的最终值。
#因为要求最小值最大,所以分堆的时候会尽量使每一堆的数据尽量均匀且接近最小值mid,
#具体地,对于其中一对a[i],在最小堆值为mid的条件下,最多可分为a[i]/mid堆。
#记所有堆可分别的堆数位cnt(a[0]/mid+....+a[n-1]/mid),
#若cnt<m,堆数不够,需减小mid,设右边界right=mid-1;
#若cnt>m,需增大mid,设左边界left=mid+1;
#若cnt==m,也不一定就是最终答案,因为mid稍微增大一点可能cnt的值并不会改变,还要继续向后找,left=mid+1.
class Solution: def solve(self , n , m , a ): if n == m: return min(a) left, right = 1, min(a) while left<right: mid = (left+right+1) >> 1 #二分法取mid值; total = sum(nums//mid for nums in a) #当mid为分m堆后的最小值时,共可以分total堆; if total >= m: left = mid #当最小值为mid的时候,堆数大于等于m,说明mid可能最小值中的最大也可能不是,说不定mid也满足total = m; else: right = mid-1 #total小于m,说明mid大了,分得堆数小于m,需要减小m return left