分享巧克力

Submission

运行时间: 75 ms

内存: 17.0 MB

class Solution:
    def maximizeSweetness(self, sweetness: List[int], k: int) -> int:
        left = min(sweetness)
        right = sum(sweetness) // (k + 1)
        while left < right:
            tmp_sum = 0
            p = 0
            mid = (left + right +1) // 2
            for sw in sweetness:
                tmp_sum += sw
                if tmp_sum >= mid:
                    tmp_sum = 0
                    p += 1
            if p >= k + 1:
                left = mid
            else:
                right = mid - 1 
        return right      

Explain

本题的思路基于二分搜索。目标是找到最大的最小巧克力量,使得可以至少分成k+1份,每份的巧克力量至少是这个最小值。我们通过设置搜索范围left和right,left是单块巧克力的最小值,right是所有巧克力总量除以k+1的结果。通过二分搜索,逐渐缩小这个范围来找到最大的最小值。在每一步的二分搜索中,我们检查能否生成至少k+1块巧克力,每块至少有mid的甜度。如果可以,我们尝试一个更大的最小值(增加left),否则减小这个值(减小right)。重复这个过程直到left和right相遇,此时的right即为所求。

时间复杂度: O(n log(sum(sweetness) / (k + 1)))

空间复杂度: O(1)

class Solution:
    def maximizeSweetness(self, sweetness: List[int], k: int) -> int:
        left = min(sweetness)  # 最小单块甜度
        right = sum(sweetness) // (k + 1)  # 最大可能的最小甜度
        while left < right:
            tmp_sum = 0  # 当前分块的甜度总和
            p = 0  # 分成的块数
            mid = (left + right +1) // 2  # 当前尝试的最小甜度值
            for sw in sweetness:
                tmp_sum += sw
                if tmp_sum >= mid:  # 如果当前块的甜度达到了mid,重新开始计数
                    tmp_sum = 0
                    p += 1
            if p >= k + 1:  # 如果可以分成超过k+1块,尝试更大的甜度值
                left = mid
            else:  # 否则尝试更小的甜度值
                right = mid - 1 
        return right  # 最终的最大最小甜度值

Explore

右边界right被设置为所有巧克力总量除以k+1,是因为我们需要找到最大的最小甜度值,使得可以至少分成k+1份。如果我们将每一份的甜度设为总甜度除以k+1,那么这是在理想情况下每一份可以达到的最大甜度值。设置这个值为right的初始值,是因为任何大于这个值的甜度都不可能实现至少k+1份的要求,因此这个值是搜索的一个合理上界。

在二分搜索中使用`(left + right + 1) // 2`作为mid的计算方式主要是为了确保在left与right非常接近时,mid能够适当地偏向right,从而避免在某些情况下进入死循环。特别是当left和right相差1时,使用`(left + right) // 2`可能会导致mid重复地等于left,从而使得搜索陷入无法前进的状态。使用`(left + right + 1) // 2`则可以确保mid在数值上能够向right逼近,有助于搜索过程的顺利进行。

将tmp_sum重置为0的原因在于我们需要开始计算新的一块巧克力块,以确保每块都至少有mid的甜度。这种做法并不会导致巧克力的浪费,而是为了确保每一块巧克力的甜度都符合题目要求的最小甜度mid。如果不重置tmp_sum,那么累积的甜度会超过mid,这可能导致无法达到至少k+1块的条件,因为超出的甜度可能会使得其中一些块的甜度不足。因此,每当一块巧克力的甜度达到了mid,我们就完成了对这一块的计算,并开始为下一块计算,确保所有块都能公平地分配甜度。