贪心-插空-5831. 你可以工作的最大周数
2021-08-01 22:01:47
问题描述:
给你 n 个项目,编号从 0 到 n - 1 。同时给你一个整数数组 milestones ,其中每个 milestones[i] 表示第 i 个项目中的阶段任务数量。
你可以按下面两个规则参与项目中的工作:
每周,你将会完成 某一个 项目中的 恰好一个 阶段任务。你每周都 必须 工作。
在 连续的 两周中,你 不能 参与并完成同一个项目中的两个阶段任务。
一旦所有项目中的全部阶段任务都完成,或者仅剩余一个阶段任务都会导致你违反上面的规则,那么你将 停止工作 。注意,由于这些条件的限制,你可能无法完成所有阶段任务。
返回在不违反上面规则的情况下你 最多 能工作多少周。
示例 1:
输入:milestones = [1,2,3]
输出:6
解释:一种可能的情形是:
- 第 1 周,你参与并完成项目 0 中的一个阶段任务。
- 第 2 周,你参与并完成项目 2 中的一个阶段任务。
- 第 3 周,你参与并完成项目 1 中的一个阶段任务。
- 第 4 周,你参与并完成项目 2 中的一个阶段任务。
- 第 5 周,你参与并完成项目 1 中的一个阶段任务。
- 第 6 周,你参与并完成项目 2 中的一个阶段任务。
总周数是 6 。
示例 2:
输入:milestones = [5,2,1]
输出:7
解释:一种可能的情形是:
- 第 1 周,你参与并完成项目 0 中的一个阶段任务。
- 第 2 周,你参与并完成项目 1 中的一个阶段任务。
- 第 3 周,你参与并完成项目 0 中的一个阶段任务。
- 第 4 周,你参与并完成项目 1 中的一个阶段任务。
- 第 5 周,你参与并完成项目 0 中的一个阶段任务。
- 第 6 周,你参与并完成项目 2 中的一个阶段任务。
- 第 7 周,你参与并完成项目 0 中的一个阶段任务。
总周数是 7 。
注意,你不能在第 8 周参与完成项目 0 中的最后一个阶段任务,因为这会违反规则。
因此,项目 0 中会有一个阶段任务维持未完成状态。
提示:
n == milestones.length
1 <= n <= 105
1 <= milestones[i] <= 109
问题求解:
周赛第二题,最初的考虑是使用优先队列维护一下,但是发现在最后的几个case上一直过不去,就知道这条路是条死路。
实际上,本题是一个完全贪心求解的问题,重要的是要分析得到一个很重要的点:耗时最长的任务如果能够被完成,那么所有的任务都能被完成。
原因如下:
举例[5, 2, 1],5,5,5,5,5中有5 + 1 = 6个空,如果能将5完全分隔开,那么后面的数字只需要从头开始继续插入即可。
那么什么情况下能够将最大的数字完全分隔开呢?
显然对于剩余的所有数字,其间隔为rest + 1,如果maxn <= rest + 1,那么就可以将最大的数字完全分隔开来,在这种情况下,所有的数字都能被满足;
如果maxn > rest + 1,那么最大的数字没有办法被完全分隔,因此最终的结果是rest * 2 + 1。
class Solution: def numberOfWeeks(self, milestones: List[int]) -> int: maxn = max(milestones) total = sum(milestones) rest = total - maxn if maxn > rest + 1: return rest * 2 + 1 else: return total