思路:
一次哈希,边哈希边检测另一个数字是否已经在dict中(二次哈希也可)
时间复杂度O(n) 空间复杂度O(n)
PS: 其实还可以先排序再双指针(沿用3sum的思路),这样操作时间复杂度O(nlogn)空间复杂度O(1)
import copy
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
d = {}
for i in range(len(nums)):
complement = target - nums[i]
# hash的时候检测另一个数字是否已存在,即使是重复数字还未覆盖也不影响
if complement in d.keys():
return [d[complement], i]
d[nums[i]] = i
return -1
思路:
时间复杂度 O(n^2) 空间复杂度O(1)
注意:题目中要求结果不重复,所以需要加上重复数字判断
(做的时候也有考虑过双指针+二分查找最后一个数,但是这样哪个指针移动无法判断)
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
res = []
if len(nums) < 3 or nums[0]>0:
return []
for i in range(len(nums)-2):
# 防止重复重复数字出现
if i != 0 and nums[i] == nums[i-1]:
continue
a = nums[i]
l = i + 1
r = len(nums) - 1
while l < r:
if nums[l] + nums[r] == 0 - a:
res.append([a, nums[l], nums[r]])
# 防止重复数字出现(只用于sum==target时)
while l 0:
r -= 1
else:
l += 1
return res
思路:
沿用3sum的思想
时间复杂度 O(n^3) 空间复杂度O(1)
注意:题目中要求结果不重复,所以需要加上重复数字判断
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
nums.sort()
n = len(nums)
res = []
for i in range(n-3):
if i!=0 and nums[i-1] == nums[i]:
continue
for j in range(i+1, n-2):
if j > i+1 and nums[j-1] == nums[j]:
continue
twosum = target - nums[i] - nums[j]
l = j+1
r = n-1
while l twosum:
r -= 1
else:
l += 1
return res
类似 3sum 的方法:
时间复杂度O(N^(K-1)) 注:k为k sum
空间复杂度O(1)
python版本:
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
return self.nSum(nums, target, 4)
def nSum(self, nums, target, n):
def dfs(pos: int, cur: List[int], n: int, target: int):
# 双指针
if n == 2:
j = pos
k = len(nums) - 1
while j < k:
sum = nums[j] + nums[k]
if sum < target:
j += 1
elif sum > target:
k -= 1
else:
# 结果添加前面n-2位数字
solution = cur[:] + [nums[j], nums[k]]
ans.append(solution)
while j < k and nums[j] == nums[j+1]:
j += 1
while j < k and nums[k] == nums[k-1]:
k -= 1
j += 1
k -= 1
return
i = pos
while i < len(nums) - n + 1:
# 剪枝的一种情况
if nums[i] * n > target or nums[-1] * n < target:
break
# 排除重复数字
if i > pos and nums[i] == nums[i-1]:
i += 1
continue
#回溯法取到全部数字
cur.append(nums[i])
dfs(i+1, cur, n-1, target-nums[i]) # 回溯
cur.pop()
i += 1
ans = []
nums.sort()
dfs(0, [], n, target)
return ans
c++ 版本:
class Solution {
public:
vector> res;
vector nums;
vector> fourSum(vector& nums, int target) {
int len = nums.size();
if(len < 4){
return res;
}
sort(nums.begin(),nums.end());
this->nums = nums;
vector cur;
dfs(0, target, 4, cur);
return res;
}
void dfs(int pos, int target, int n, vector& cur){
if(n == 2){
int left = pos;
int right = nums.size() - 1;
while(left < right){
long sum = (long)nums[left] + (long)nums[right];
if(sum < target){
left++;
}else if (sum > target){
right--;
}else{
//此处重新赋值可以使得参数cur使用引用,从而避免大量的无用复制,大幅度提高效率。
vector tmp(cur.begin(),cur.end());
tmp.push_back(nums[left]);
tmp.push_back(nums[right]);
res.push_back(tmp);
while(left < right && nums[left] == nums[left + 1])
left++;
while(left < right && nums[right] == nums[right - 1])
right--;
left++;
right--;
}
}
return;
}
int i = pos;
while(i < nums.size() - n + 1){
if(nums[i] * n > target && nums[nums.size() - 1] * n < target){
break;
}
if(i > pos && nums[i] == nums[i - 1]){
i++;
continue;
}
cur.push_back(nums[i]);
dfs(i + 1, target - nums[i],n - 1,cur);
cur.pop_back();
i++;
}
}
};