目录
题目描述:
给定一个包含 n 个整数的数组 nums
和一个目标值 target
,判断 nums
中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target
相等?找出所有满足条件且不重复的四元组。
注意:
答案中不可以包含重复的四元组。
示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。 满足要求的四元组集合为: [ [-1, 0, 0, 1], [-2, -1, 1, 2], [-2, 0, 0, 2] ]
解题思路:
先排序,在定四个索引: a, b, c, d; 其中a, b依次从头到尾开始遍历,c定在b+1,d定在nums.size()-1, 然后c, d慢慢靠拢。如果nums[a] + nums[b] + nums[c] + nums[d] > target,在前面基数a,b固定的情况下,则只能移动d--,才能使和变小,才有可能找到相等的索引,反之如果<target,则只能c++
C++代码:
执行用时:112 ms, 在所有 C++ 提交中击败了20.99%的用户
内存消耗:12.6 MB, 在所有 C++ 提交中击败了87.95%的用户
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int len_nums = nums.size();
if (len_nums < 4) return {};
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
for (int i = 0; i < len_nums-3; i++) // i指向四个数中第一个元素
{
if (i > 0 && nums[i] == nums[i-1]) continue; // 后面的数字和前面的重复了,则直接跳过
for (int j = i+1; j < len_nums-2; j++) // j指向四个数中第二个元素
{
if (j > i+1 && nums[j] == nums[j-1]) continue; // 后面的数字和前面的重复了,则直接跳过
int L = j+1; // L指向四个数中第三个元素
int R = len_nums-1;
while (L < R) // 遍历,两边靠拢
{
// nums[i]+nums[j]+nums[L]+nums[R] > target
if (nums[i]+nums[j]-target > -(nums[L]+nums[R])) R--; // 大了,则移动右边
else if (nums[i]+nums[j]-target < -(nums[L]+nums[R])) L++; // 小了,则移动左边
else
{
ans.push_back({nums[i], nums[j], nums[L], nums[R]}); // 找到了合适的,如果后面元素重复则跳过
while (L < R && nums[L] == nums[L+1]) L++; // 2, 3, 3, 4. 本来L=2, 后面则L=3
while (L < R && nums[R] == nums[R-1]) R--;
L++; // L=4
R--;
}
}
}
}
return ans;
}
};
python代码:
执行用时:476 ms, 在所有 Python 提交中击败了64.67%的用户
内存消耗:13 MB, 在所有 Python 提交中击败了78.96%的用户
class Solution(object):
def fourSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[List[int]]
"""
len_nums = len(nums)
if len_nums < 4: return []
nums.sort() # 有序数组
ans = []
for i in range(len_nums - 3):
if i > 0 and nums[i] == nums[i-1]: continue # 重复了,则跳过
for j in range(i + 1, len_nums - 2):
if j > i+1 and nums[j] == nums[j-1]: continue
L = j + 1
R = len_nums - 1
while L < R:
sum_val = nums[i] + nums[j] + nums[L] + nums[R]
if sum_val > target:
R = R - 1
elif sum_val < target:
L = L + 1
else:
ans.append([nums[i], nums[j], nums[L], nums[R]]) # 找到了,如果后面元素相等,则跳过
while L < R and nums[L] == nums[L+1]: L = L + 1
while L < R and nums[R] == nums[R-1]: R = R - 1
L = L + 1 # 和变大
R = R - 1 # 和变小
return ans