难度: Hard
Submission
运行时间: 31 ms
内存: 16.1 MB
class Solution: def minBuildTime(self, blocks: List[int], split: int) -> int: def check(x: int) -> int: if x == 0: return False s = 1 t = 0 i = len(blocks) - 1 while t <= x and i >= 0: if s >= i + 1: return True while i >= 0 and t + split > x - blocks[i]: s -= 1 if s < 0: return False i -= 1 t += split s *= 2 if i < 0: return True return False left, right = 0, 1000000 blocks.sort() while left <= right: mid = left + (right - left) // 2 if check(mid): right = mid - 1 else: left = mid + 1 return left
Explain
题解采用二分查找和贪心算法的组合。首先对blocks数组进行排序,以便使用贪心策略。定义一个辅助函数check(x),该函数用来判断是否可以在时间x内完成所有blocks的建造。在check函数中,使用一个贪心的方法,模拟以时间x为限制条件下的工作流程。如果在时间x内可以完成建造,返回True;否则返回False。在主函数中,通过二分查找的方法,寻找满足条件的最小时间x。
时间复杂度: O(n log(max(blocks)))
空间复杂度: O(n)
class Solution: def minBuildTime(self, blocks: List[int], split: int) -> int: def check(x: int) -> int: if x == 0: return False s = 1 # 初始化工人数量为1 t = 0 # 初始化当前耗时为0 i = len(blocks) - 1 # 从最大的block开始 while t <= x and i >= 0: if s >= i + 1: return True # 如果工人数足够,则直接完成 while i >= 0 and t + split > x - blocks[i]: s -= 1 # 工人不足,需要等待 if s < 0: return False # 工人数为负,不可能完成 i -= 1 t += split # 增加分裂时间 s *= 2 # 工人数翻倍 if i < 0: return True # 所有block都已处理 return False left, right = 0, 1000000 # 初始化二分查找范围 blocks.sort() # 排序blocks while left <= right: mid = left + (right - left) // 2 # 计算中间值 if check(mid): right = mid - 1 # 缩小查找范围 else: left = mid + 1 # 扩大查找范围 return left # 返回最小可能时间
Explore
从blocks数组的最大值开始处理是因为这些大的block通常需要更长的时间来完成,而且它们对于确定是否能在给定的时间内完成所有任务影响更大。处理最大的blocks首先可以更快地判断出不可能在时间限制内完成的情况,从而提高算法的效率。此外,从大到小的处理顺序可以帮助尽可能地利用现有的时间,因为大的blocks如果不能在限制时间内完成,小的blocks自然也难以在剩余时间内完成。
初始的`right`值为1000000是一个基于问题规模和实际情况的估计值。此值应足够大,以确保它覆盖所有可能的最大构建时间。这个值通常是基于对输入数据(如blocks数组中的最大值)和split时间的理解。在没有具体数据或明确的时间限制要求的情况下,选择一个大的数值如1000000,可以确保二分查找的上界覆盖所有可能的情况,但在实际应用中,这个值可能需要根据具体问题的数据范围进行调整。
检查`i >= 0 and t + split > x - blocks[i]`是为了确保在当前的时间限制x内,即使工人数翻倍后,也有足够的时间来完成当前处理的block。这一检查是为了验证在增加了分裂时间(即新的工人准备时间)后,是否还有足够的剩余时间来处理当前的block。如果处理当前block所需的时间加上分裂时间超过了总的时间限制,那么这表明在当前的时间限制内无法完成建造,因此需要调整时间限制。这一步骤是为了保证即使资源(工人数)扩充,也要满足时间上的可行性。
实际上,在给定的代码中,工人数`s`从1开始且在每次循环时都会翻倍,因此`s`不会小于0。这部分代码的描述可能是一个逻辑错误或者解释错误。正确的应该是,如果在任何时点工人数量不足以继续工作,则可以考虑返回False。即,如果在处理过程中发现需要的工人数大于当前的工人数,那么应该返回False。在代码实现中,应确保逻辑一致性和描述准确性。