3Sum and 4Sum Problems
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之前,對相鄰兩個元素是否相等做了判斷,避免相同的數被重復考察;同樣地,代碼在將左指針向右移動之後,也判斷了新的元素是否與剛剛考察過的前一個元素相等,若是相等,則將指針繼續右移,減少重復計算;
3Sum and 4Sum Problems