LeetCode #15 2018-07-27
2018-07-27 本文已影响0人
40巨盗
15. 3Sum
Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4],
A solution set is:
[
[-1, 0, 1],
[-1, -1, 2]
]
https://leetcode.com/problems/3sum/description/
这道题和Two Sum有所不同,使用哈希表的解法并不是很方便,因为结果数组中元素可能重复,如果不排序对于重复的处理将会比较麻烦,因此这道题一般使用排序之后夹逼的方法,总的时间复杂度为O(n2+nlogn)=(n2),空间复杂度是O(n), 注意,在这里为了避免重复结果,对于已经判断过的数会skip掉,这也是排序带来的方便。 这道题考察的点其实和Two Sum差不多,Two Sum是3Sum的一个subroutine。
代码如下:
class Solution(object):
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
result = []
if not nums or len(nums) < 3:
return result
nums.sort()
for i, num in enumerate(nums[len(nums) - 1:1:-1]):
cur_index = len(nums) - i - 1
if cur_index < len(nums) - 1 and nums[cur_index] == nums[cur_index + 1]:
continue
cur_res = self.twoSum(nums, 0, cur_index - 1, -num)
for res in cur_res:
res.append(num)
result.extend(cur_res)
return result
def twoSum(self, nums, left, right, target):
cur_res = []
while(left < right):
if nums[left] + nums[right] == target:
temp_res = [nums[left], nums[right]]
cur_res.append(temp_res)
left += 1
right -= 1
while(left < right and nums[left] == nums[left - 1]):
left += 1
while(left < right and nums[right] == nums[right + 1]):
right -= 1
elif nums[left] + nums[right] < target:
left += 1
else:
right -= 1
return cur_res
感悟:
- 由于list.append()是从后面进行添加,而且题目要求结果数组中的数字升序,所以最后添加进list的一定要是最大的,所以for循环应该从len(nums) - 1扫到2.
- 为了避免结果重复,我们要跳过已经判断过的数:
if cur_index < len(nums) - 1 and nums[cur_index] == nums[cur_index + 1]:
continue
这点很重要,在很多有重复的数组中,为了避免重复的结果产生,都需要使用这个判断。
- 因为可能有多组2个数的和为-nums[i], 所以在找到一组后,要跳过重复元素,然后继续寻找。
while(left < right and nums[left] == nums[left - 1]):
left += 1
while(left < right and nums[right] == nums[right + 1]):
right -= 1