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的人來說,也更好理解了,不過運行效率也沒有提升。至於哪種方式好,就是另外一個問題了。
Python 解LeetCode:Intersection of Two Arrays