1. 题目描述
有 n 个活动即将举办,每个活动都有开始时间与活动的结束时间,第 i 个活动的开始时间是 starti ,第 i 个活动的结束时间是 endi ,举办某个活动就需要为该活动准备一个活动主持人。
一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,一个主持人参与了第 i 个活动,那么该主持人在 (starti,endi) 这个时间段不能参与其他任何活动。求为了成功举办这 n 个活动,最少需要多少名主持人。
题目来源: https://www.nowcoder.com/practice/4edf6e6d01554870a12f218c94e8a299
2. 分析
这道题刚开始想用模拟的方法来做,思路非常直观:即考虑当前活动时,检查是否已经有活动已经结束了。如果有,那我们直接重用那个活动的主持人,否则,添加一个新的主持人!数学化表达如下:
对于活动
,检查是否有活动
,使得
,如果存在,则不需要添加新的主持人,否则需要增加一个主持人
在具体实现时,我并没有写出类似标准答案的优美方案,而是如下的代码:
def minmumNumberOfHost(self , n, startEnd):
# although item in startEnd is a list, it can be sorted
startEnd.sort()
# to represent a host with its end time
arr = []
arr.append(startEnd[0][1])
for item in startEnd[1:]:
start, end = item[0], item[1]
if start >= arr[0]:
# reuse a host and update its end time (sorted)
# here is the problem, I adopt an ugly solution
del arr[0]
arr.append(end)
# sort it! help to choose most suitable activity
arr.sort()
else:
arr.append(end)
arr.sort()
return len(arr)
运行时,我的方案在部分用例上超时了。之后查看其它方案发现思路是一致的,我的问题出现在未采用合适的数据结/变量来表示这一关系。接下来查看优美的标准方案:
def minmumNumberOfHost(self, n: int, startEnd: List[List[int]]) -> int:
# write code here
start = []
end = []
# collect all activities' timezone in separated arraies
for item in startEnd:
start.append(item[0])
end.append(item[1])
# sort all the timezones to help tag used one
start.sort()
end.sort()
# j is used to tag reused activity
j, host = 0, 0
for i in range(0, n):
current = start[i]
# now: given an activity, check whether
# 1) add a new host
# 2) reuse an existing host
if current < end[j]: # can not reuse the most likely one
host += 1 # update status: add a new host
else: # ok, we resue an ended activity
j += 1
return host
可以看到,整体的逻辑框架非常类似。问题在于,为什么我没有想到标准方案的表达方式?
3. 零碎思考
- 1)虽然标准方案的思路容易理解,但实际上自己思考时并不容易想到这样去做,尤其是数据结构的选择。要认识到标准方案的好是经过了多次选择和优化的结果,结合次一点的方案,可帮助发现自身的思考盲区。
- 2) 算法的核心在于两个方面:数据结构的选择(例如变量,数组)和逻辑关系的表达(例如条件,循环等)。逻辑关系的表达可以先从high-level入手,然后设计数学表达式进行抽象;而数据结构的选择,则需要经验和灵感,目前还没有什么好的方法。本题两个方案的对比,可以帮助更清晰的看出两种方案的差别,记录常看常新。
- 3) 初次写出的代码逻辑仍然存在优化空间,比如存在两处"arr.append(end) arr.sort()"语句,可以合并。思考状态更新时,我们究竟需要保存哪些信息就足够了?【好的方案容易理解,但实际上还是不太容易优化到,需要多多思考为什么】
- 4)看似简单的小例子其实是非常好的分析工具,比如可方便记录每一步的状态更新,它能更具体,更细节的去定位设计方案的有效性以及出现的差错。