给定一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4], 满足要求的三元组集合为: [ [-1, 0, 1], [-1, -1, 2] ]
超时答案:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int size = nums.size();
vector<vector<int>> resultList;
if (size == 0 || size == 1 || size == 2) return resultList;
sort(nums.begin(), nums.end());
map<vector<int>, int> pool;
for (int cursor = 0; cursor < size; cursor++) {
int firstIndex = 0;
if (cursor == 0 || cursor == (size - 1))
continue;
while (firstIndex < cursor) {
if (nums[firstIndex] > 0)
break;
int lastIndex = size - 1;
while (lastIndex > cursor) {
if (nums [lastIndex] < 0)
break;
if ((nums [firstIndex] + nums [cursor] + nums [lastIndex]) == 0) {
vector<int> temp = { nums [firstIndex], nums [cursor], nums [lastIndex] };
if (!pool.count(temp)) {
pool [temp] = cursor;
resultList.push_back(temp);
}
}
lastIndex--;
}
firstIndex++;
}
}
return resultList;
}
};
完成答案:
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int size = nums.size();
vector<vector<int>> resultList;
if (size == 0 || size == 1 || size == 2) return resultList;
sort(nums.begin(), nums.end());
map<vector<int>, int> pool;
for (int cursor = 0; cursor < size; cursor++) {
int firstIndex = 0;
int lastIndex = size - 1;
int target = -nums [cursor];
if (cursor == 0 || cursor == (size - 1))
continue;
while (firstIndex < cursor && lastIndex > cursor) {
if (nums [firstIndex] > 0 || nums [lastIndex] < 0)break;
if ((nums [firstIndex] + nums [lastIndex]) > target)
lastIndex--;
else if ((nums [firstIndex] + nums [lastIndex]) < target)
firstIndex++;
else {
vector<int> temp = { nums [firstIndex], nums [cursor], nums [lastIndex] };
if (!pool.count(temp)) {
pool [temp] = cursor;
resultList.push_back(temp);
}
lastIndex--;
firstIndex++;
}
}
}
return resultList;
}
};
这道题凭自己能力只能解到超时的答案,因此才把超时的答案贴出来,完成的答案实际是读了这篇博客,但并没有看代码只是看了前边一段讲解。对比超时答案和完成答案其实基本差不多,最大不同的地方在于:
前索引和后索引的移动条件是什么,这个点我没有想到,因此直接导致实现上多了一层循环,而其移动条件是两者的和与锁定值之间进行比较,小了前索引加一,大了后索引减一,为何这个办法会有效主要是因为前面做了一次排序,而前面使用排序的最大原因就在这儿。
当然和其他答案相比还有一些没有考虑到,比如防止重复的实现上不同。
这道题最好先看两个数相加的解法才好理解三个数相加的实现,其中有很多有意思的地方。