这道题,真的,我哭晕在撤硕儿,搞了一下午。链接放在这里。
题目是这样的。
这道题之所以坑爹甚至一度想揍力扣程序员的地方在于我不停地超时,疯狂地超时,你康康它的测试用例,这tm还是人吗?!
我先把最初的代码放到这里,这是我经过2个多小时调试和优化过的,自认为已经不错了
from typing import List
class Solution:
def maxEvents(self, events: List[List[int]]) -> int:
Days = [] # 参赛的日期
# 对数组进行复合排序,先对第二列从小到大排序,在此基础上对第一列进行从小到大排序
# 时间复杂度o(nlogn)
events.sort(key=lambda x: (x[1], x[0])) # 这一句和下边5句一个功能,可见。。。(论憨批能有多憨
# events.sort(key=lambda x: x[1])
# for i in range(len(events)-1):
# if events[i][1] == events[i+1][1]:
# if events[i][0] > events[i+1][0]:
# events[i], events[i+1] = events[i+1], events[i]
for i in events:
for j in range(i[0], i[1]+1):
if j not in Days:
Days.append(j)
break
return len(Days)
这是一道典型的扫描算法题。由于每个时间点最多参加一个会议,我们可以从1开始遍历所有时间。对于每一个时间点,所有在当前时间及之前时间开始,并且在当前时间还未结束的会议都是可参加的。
显然,在所有可参加的会议中,选择结束时间最早的会议是最优的,因为其他会议还有更多的机会可以去参加。
思路不错(贪心算法),但是超时了。
用python写代码的最大优点就是简洁高效,你看我核心代码不超过6行,换成Java C++肯定不行。
缺点就一点坑爹了,同样是暴力法求解,人家C++同学就完美跨过各种奇葩用例,python就经常死在超时的路上,然后你要么剪枝,要么优化代码,要么想更巧妙的办法。
set? WHY?
刚刚我看了其他路大神的解法,在骂它坑爹的同时确实有python通过了的,核心思想就是把Days的List类型换成了set类型。
'''
新的解法,爷把Days从List类型换成set就通过了。。。
草他妈的
为啥!!!
'''
class Solution:
def maxEvents(self, events: List[List[int]]) -> int:
# 对数组进行复合排序,先对第二列从小到大排序,在此基础上对第一列进行从小到大排序
# 时间复杂度o(nlogn)
events.sort(key=lambda x: (x[1], x[0]))
# 这里把Days设置成set,然后就不超时了,很迷
Days = set()
for i in events:
for j in range(i[0], i[1]+1):
if j not in Days:
Days.add(j)
break
return len(Days)
原谅我在编程时候爆粗口了。。。当时确实气。。。
松一口气之余我又开始想,这是为啥呢?
真相
原来,在python中set、dict和list是不同的数据结构,在查找元素的时候,list是从头到尾挨个遍历对比,时间复杂度为o(n),而set和dict用的是哈希表,时间复杂度o(1),对应于我这个变态的用例,用到的查找次数太多辽,所以用set比list好得多。
话说我以前一直天真的认为python中列表是做了哈希处理的,今天打脸了,还是继续努力呀!
感恩LeetCode工作人员