【leetcode刷題】20T10-三數之和
- 2020 年 2 月 16 日
- 筆記
木又同學2020年第10篇解題報告
leetcode第15題:三數之和
https://leetcode-cn.com/problems/3sum/
【題目】
給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重複的三元組。
注意:答案中不可以包含重複的三元組。
示例: 給定數組 nums = [-1, 0, 1, 2, -1, -4], 滿足要求的三元組集合為: [ [-1, 0, 1], [-1, -1, 2] ]
【思路】
暴力解法,三層循環,判斷三數相加是否為0;要想得到唯一的三元組,還需要再次判斷。
當然可以優化,遇到時間複雜度太高的,一般可以先排個序。排序以後,即使是三層循環,第一個數大於0,由於後兩個數均大於0,不可能三數之和等於0;同理,前兩個數之和大於0,第三個數肯定大於0,三數之和也肯定不等於0。
再次優化,使用字典存儲元素及該元素在數組中最後位置。這樣,對於一組nums[p1]和nums[p2],查找nums[p2+1:]是否存在-nums[p1]-nums[p2]只需要O(1)的複雜度,時間複雜度降為O(n^2)
本來以為OK了,但是每次判斷結果res中是否存在某個三元組,需要O(m)的時間,導致一直通不過所有case。其實,由於nums已經排序,得到的nums[p1],nums[p2]以及p2之後的-nums[p1]-nums[p3]肯定升序排列的。因此,只要保證nums[p1]和nums[p2]不同即可。
【代碼】
python版本
class Solution(object): def threeSum(self, nums): """ :type nums: List[int] :rtype: List[List[int]] """ res = [] if len(nums) < 3: return res nums.sort() # 存儲下標,降低查找的時間複雜度 d = {} for i, n in enumerate(nums): d[n] = i for i in range(len(nums)-2): # 重複元素 if i > 0 and nums[i] == nums[i-1]: continue # 最小的數大於0,其餘的不用判斷 if nums[i] > 0: break for j in range(i+1, len(nums)-1): # nums[i] + nums[j] > 0,j後續元素都大於0,不用判斷 if nums[i] + nums[j] > 0: break if j > i+1 and nums[j] == nums[j-1]: continue if d.get(-nums[i]-nums[j], -1) > j: res.append([nums[i], nums[j], -nums[i]-nums[j]]) return res