3Sum:
题目: Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1.
The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
审题: 输入都是整数,因此与target的最小可能距离为0,当每次获得三个值的和时,首先应该判断一下是否与target相等,也即他们的距离为0,这样可以避免一些多余的计算,减少计算量。
class Solution:
# @return an integer
def threeSumClosest(self, num, target):
num.sort()
result = num[0] + num[1] + num[2]
for i in range(len(num) - 2):
j, k = i+1, len(num) - 1
while j < k:
sum = num[i] + num[j] + num[k]
if sum == target:
return sum
if abs(sum - target) < abs(result - target):
result = sum
if sum < target:
j += 1
elif sum > target:
k -= 1
return result
通过设置左右指针,将一个一般会按照O(N3) 复杂度的问题降低为O(N2)。这里要注意最外面的循环截止N-2,预留两个索引位给两个pointers.
4Sum
题目 Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target. Note: The solution set must not contain duplicate quadruplets. For example, given array S = [1, 0, -1, 0, -2, 2], and target = 0. A solution set is: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
方案
class Solution:
def fourSum(self, nums, target):
def NSum(nums, target, N, result, results):
if len(nums) < N or N < 2 or target < nums[0]*N or target > nums[-1]*N:
return
if N == 2:
r = len(nums)-1
l = 0
while l < r:
s = nums[l] + nums[r]
if s == target:
results.append(result + [nums[l], nums[r]])
l += 1
while l < r and nums[l] == nums[l-1]:
l += 1
elif s > target:
r -= 1
else:
l += 1
else:
for i in range(len(nums)-N+1):
if i == 0 or (i > 0 and nums[i] != nums[i-1]):
NSum(nums[i+1:], target-nums[i], N-1, result+[nums[i]], results)
results = []
nums.sort()
NSum(nums, target, 4, [], results)
return results
解析 (1)这里实现了一个NSum的算法,最底层实现了2Sum问题,然后递归地调用2Sum实现Nsum; (2)在进入代码主体之前,先通过判断排除各种极端和特殊的情形,当然这也算是代码的主体; (3)代码在调用Nsum之前,对相邻两个元素是否相等做了判断,避免相同的数被重复考察;同样地,代码在将左指针向右移动之后,也判断了新的元素是否与刚刚考察过的前一个元素相等,若是相等,则将指针继续右移,减少重复计算;