算法题目-活动调度

1. 题目描述

有 n 个活动即将举办,每个活动都有开始时间与活动的结束时间,第 i 个活动的开始时间是 starti ,第 i 个活动的结束时间是 endi ,举办某个活动就需要为该活动准备一个活动主持人。

一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,一个主持人参与了第 i 个活动,那么该主持人在 (starti,endi) 这个时间段不能参与其他任何活动。求为了成功举办这 n 个活动,最少需要多少名主持人。

题目来源: https://www.nowcoder.com/practice/4edf6e6d01554870a12f218c94e8a299

2. 分析 

这道题刚开始想用模拟的方法来做,思路非常直观:即考虑当前活动时,检查是否已经有活动已经结束了。如果有,那我们直接重用那个活动的主持人,否则,添加一个新的主持人!数学化表达如下:

对于活动 i,检查是否有活动 j,使得 end_j \le start_i,如果存在,则不需要添加新的主持人,否则需要增加一个主持人

 在具体实现时,我并没有写出类似标准答案的优美方案,而是如下的代码:

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)看似简单的小例子其实是非常好的分析工具,比如可方便记录每一步的状态更新,它能更具体,更细节的去定位设计方案的有效性以及出现的差错。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值