查看: 3949| 回复: 14
跳转到指定楼层
上一主题 下一主题
收起左侧

[动态规划] 求这道面经题的解法

全局:
5小米
给你一堆Events,每个Event有start time和end time。Events的时间可能overlap。计算一个人当天最多可以参加几个events。



上一篇:转码master暑期没实习该如何度过
下一篇:最少修改次数还原航线
🔗
moluren 2019-6-10 22:01:30 | 只看该作者
全局:
这道题貌似与以下interval相关的题目类似:
给定一堆interval,问最多的不相交的interval的个数是多少。

对于interval的问题,基本方法就是两个:排序然后使用贪心算法。
贪心算法的策略是:排序后,两个相交的interval移除EndTime大的那个。

回到楼主题目,我建议的思路是:排序,使用贪心算按天统计不相交的interval(Event)的数量。

补充内容 (2019-6-10 22:02):
时间复杂度:整体排序O(NLogN),计算不相交的Interval数需要进行一次O(N)遍历。
因而整体时间复杂度是O(NLogN)
回复

使用道具 举报

🔗
337845818 2019-6-11 05:40:27 | 只看该作者
全局:
背包题目, 经典greedy题目.
按结束时间排序即可
回复

使用道具 举报

🔗
 楼主| user123456 2019-6-11 08:34:47 | 只看该作者
全局:
感觉greedy似乎不行。给个反例:
Events = [1, 10], [2, 15], [11, 50], [12, 13], [13, 14]
这样Greedy排出来是这么三排不overlap的时间:
[1, 10], [11, 50]
[2, 15],
[12, 13], [13, 14]
即最多是2。但下面这种选法是3:
[1, 10], [12, 13], [13, 14]
回复

使用道具 举报

🔗
wisdompeak2 2019-6-11 09:22:50 | 只看该作者
全局:
贪心法。按结束时间排序。思想是:结束时间早的区间,因为对后续的影响最小,所以我们会优先收录。
所以,我们肯定会收录第一个区间后,接着顺次考察后续的区间,只要与第一个区间重叠的都会舍弃不看,直至找到下一个与第一个区间没有重叠的区间。这是最早结束的、与第一个区间无重叠的区间,因此是最优的,收录其中。
然后重复以上的步骤,直至考察完所有的区间。

评分

参与人数 1大米 +1 收起 理由
user123456 + 1 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
 楼主| user123456 2019-6-11 17:20:06 | 只看该作者
全局:
wisdompeak2 发表于 2019-6-11 09:22
贪心法。按结束时间排序。思想是:结束时间早的区间,因为对后续的影响最小,所以我们会优先收录。
所以, ...

感觉这个方法讲得通。但还是没有说服自己为什么这么做一定是对的。即有没有可能在某一步选择最先结束的时候并不是最优的方案?不知道怎么证明这个是不可能的。
回复

使用道具 举报

🔗
 楼主| user123456 2019-6-11 17:21:43 | 只看该作者
全局:
参考楼上说的方法,写了一个代码。暂时没有找到反例:

  1. import java.util.*;

  2. public class Solution {
  3.   public static void main(String[] args) {
  4.     Event[] events = new Event[] {
  5.       new Event(1, 5),
  6.       new Event(1, 4),
  7.       new Event(2, 3),
  8.       new Event(3, 4),
  9.       new Event(4, 5),
  10.     };
  11.     List<Event> res = (new MyCode()).getMaxEvents(events);
  12.     System.out.println(res.size());
  13.     for(Event ev : res) {
  14.       ev.print();
  15.     }
  16.   }
  17. }

  18. class MyCode {
  19.   public List<Event> getMaxEvents(Event[] events) {
  20.     List<Event> res = new LinkedList<>();
  21.     if (events.length == 0) {
  22.       return res;
  23.     }
  24.     Arrays.sort(events, (e1, e2) -> e1.e - e2.e); // 按照结束时间从小到大排序
  25.     res.add(events[0]);
  26.     int lastEnd = events[0].e;
  27.     for (int i = 1; i < events.length; i++) {
  28.       Event curr = events[i];
  29.       if (curr.s >= lastEnd) {
  30.         res.add(curr);
  31.         lastEnd = curr.e;
  32.       }
  33.     }
  34.     return res;
  35.   }
  36. }

  37. class Event {
  38.   int s;
  39.   int e;
  40.   public Event(int s, int e) {
  41.     this.s = s;
  42.     this.e = e;
  43.   }
  44.   public void print() {
  45.     System.out.print("[" + this.s + ", " + this.e + "] ");
  46.   }
  47. }
复制代码
回复

使用道具 举报

🔗
wisdompeak2 2019-6-11 17:31:21 | 只看该作者
全局:
user123456 发表于 2019-6-11 17:20
感觉这个方法讲得通。但还是没有说服自己为什么这么做一定是对的。即有没有可能在某一步选择最先结束的时 ...

你不选择最先结束的区间的话,难道会选择晚结束的区间,去占用未来宝贵的时间资源吗?
回复

使用道具 举报

🔗
 楼主| user123456 2019-6-11 17:58:44 来自APP | 只看该作者
全局:
wisdompeak2 发表于 2019/06/11 17:31:21


你不选择最先结束的区间的话,难道会选择晚结束的区间,去占用未来宝贵的时间资源吗?

Hmm...这个似乎是在用假设证明基于这个假设的结论
回复

使用道具 举报

全局:
user123456 发表于 2019/06/11 08:34:47
感觉greedy似乎不行。给个反例:
Events = [1, 10], [2, 15], [11, 50], [12, 13], [13, 14]
这样Greedy排出来是这么三排不overla...

按结束时间sort
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表