题目链接:leetcode.
这道题第一反应是用回溯,不知道会不会超时
然后我记得应该是有一个把n3降为n2的方法的,比回溯的时间复杂度是低的
很好,一顿操作猛如虎,结果击败百分五
/*
执行用时:932 ms, 在所有 C++ 提交中击败了5.01%的用户
内存消耗:63 MB, 在所有 C++ 提交中击败了5.01%的用户
*/
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int N = nums.size();
if(N < 3)
return {};
unordered_map<int, vector<int>> M;
//为了跳过那些重复的值
sort(nums.begin(), nums.end());
for(int i = 0;i < N;++i)
{
M[nums[i]].push_back(i);
}
vector<vector<int>> ans;
for(int i = 0;i < N;++i)
{
//跳过重复的数
if(i && nums[i] == nums[i - 1])
{
continue;
}
for(int j = i + 1;j < N;++j)
{
if(j != i + 1 && nums[j] == nums[j - 1])
continue;
int t = nums[i] + nums[j];
if(!M[-t].empty())
{
for(auto x : M[-t])
{
//往后找不再往前找
if(x > i && x > j)
{
ans.push_back({nums[i], nums[j], nums[x]});
break;//找到了就跳,不再找了
}
}
}
}
}
return ans;
}
};
emmm我好像一个猪头,排了个序之后哈希表还有什么用呢,没有
大概可能,其实是有一点用的,就一点,打败5%的那一点
/*
315 / 318 个通过测试用例
*/
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int N = nums.size();
if(N < 3)
return {};
//为了跳过那些重复的值
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
for(int i = 0;i < N;++i)
{
//跳过重复的数
if(i && nums[i] == nums[i - 1])
{
continue;
}
for(int j = i + 1;j < N;++j)
{
if(j != i + 1 && nums[j] == nums[j - 1])
continue;
for(int k = j + 1;k < N;++k)
{
if(k != j + 1 && nums[k] == nums[k - 1])
continue;
if(nums[i] + nums[j] + nums[k] == 0)
{
ans.push_back({nums[i], nums[j], nums[k]});
}
}
}
}
return ans;
}
};
正确解法应该是用双指针来降时间复杂度了啦!
第二重循环的时候,固定了nums[j],求解出的nums[k]满足 nums[i] + nums[j] + nums[k] == 0 的话,当j++时,下一个符合条件的k'一定在k的左边
/*
执行用时:132 ms, 在所有 C++ 提交中击败了26.47%的用户
内存消耗:19.5 MB, 在所有 C++ 提交中击败了68.11%的用户
*/
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int N = nums.size();
if(N < 3)
{
return {};
}
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
int cc = N - 1;
for(int i = 0;i < N;++i)
{
if(i && nums[i] == nums[i - 1])
continue;
int j = i + 1, k = cc;
while(j < k)
{
int t = nums[i] + nums[j] + nums[k];
if(t == 0)
{
ans.push_back({nums[i], nums[j], nums[k]});
j++;
k--;
}
else if(t > 0)
{
k--;
}
else
{
j++;
}
while(j < k && j != i + 1 && nums[j] == nums[j - 1])
{
j++;
}
while(j < k && k != N - 1 && nums[k] == nums[k + 1])
{
k--;
}
}
}
return ans;
}
};
我写的太乱七八糟了,瞻仰一下官方写法
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<vector<int>> ans;
// 枚举 a
for (int first = 0; first < n; ++first) {
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// c 对应的指针初始指向数组的最右端
int third = n - 1;
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
ans.push_back({nums[first], nums[second], nums[third]});
}
}
}
return ans;
}
};
//作者:LeetCode-Solution
//链接:https://leetcode-cn.com/problems/3sum/solution/san-shu-zhi-he-by-leetcode-solution/
//来源:力扣(LeetCode)
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
5万+

被折叠的 条评论
为什么被折叠?



