Python 解LeetCode:Intersection of Two Arrays
最近,在用解决LeetCode问题的时候,做了349: Intersection of Two Arrays这个问题,就是求两个列表的交集。我这种弱鸡,第一种想法是把问题解决,而不是分析复杂度,于是写出了如下代码:
1 class Solution(object): 2 def intersection(self, nums1, nums2): 3 """ 4 :type nums1: List[int] 5 :type nums2: List[int] 6 :rtype: List[int] 7 """ 8 ret = [] 9 for i in nums1: 10 if i in nums2 and not i in ret: 11 ret.append(i) 12 return ret
打眼一看,嗯,挺好,时间负责度是O(n),点击提交,AC;打开结果一看,EXM?才击败了15%?这是O(n*2)的复杂度啊!哪里有问题呢?再一看,问题就出在i in nums2这个语句中了,在Python中,List的in操作的时间复杂度是O(n),也就是实现的算法复杂度果然是O(n2)了。看来只是单纯的看表面的循环的复杂度是不行的,还是要了解一些内部的实现。等等,这是两个列表的交集操作啊,集合才是完美的实现,python自带了集合类型set。嗯,就用集合了,又写了如下代码:
1 class Solution(object): 2 def intersection(self, nums1, nums2): 3 """ 4 :type nums1: List[int] 5 :type nums2: List[int] 6 :rtype: List[int] 7 """ 8 return list(set(nums1).intersection(set(nums2)))
提交,AC,查看结果,beat 80%,果然快了好多,代码还更加Pythonic了。对于Python的各种数据类型的时间复杂度,可以看这里。写代码的过程中,要充分了解Python的内部实现,才能运行的更快啊!
然后又看到了350. Intersection of Two Arrays II,这次的结果是两个数组的交集,但是可以有重复元素了,要运行O(n)的话,这次直接想到了用空间换时间,无非是使用hash了,Python的字典就是hash实现的,于是写了:
1 class Solution(object): 2 def intersect(self, nums1, nums2): 3 """ 4 :type nums1: List[int] 5 :type nums2: List[int] 6 :rtype: List[int] 7 """ 8 tmp_dict = dict() 9 ret = [] 10 for i in nums1: 11 tmp_dict[i] = tmp_dict[i] + 1 if tmp_dict.get(i) else 1 12 for n in nums2: 13 if tmp_dict.get(n) > 0: 14 ret.append(n) 15 tmp_dict[n] -= 1 16 return ret
提交运行,果然,击败了90%。结果不错,但是我还是想到用Python的Countrs了,这样会不会更快呢?点击打开讨论区,果然看到有这样用的:
1 class Solution(object): 2 def intersect(self, nums1, nums2): 3 """ 4 :type nums1: List[int] 5 :type nums2: List[int] 6 :rtype: List[int] 7 """ 8 a, b = map(collections.Counter, (nums1, nums2)) 9 return list((a & b).elements())
代码更短了,对于熟悉Counters的人来说,也更好理解了,不过运行效率也没有提升。至于哪种方式好,就是另外一个问题了。