三数之和
题目链接三数之和
两数之和思路
这道题我们先想两数之和怎么做呢?两数相加等于0,两重for循环暴力解答。怎么样可以更快一点呢?可以用哈希把时间复杂度从O(n^2)转为O(n)。先把每个元素想要的target值存入哈希表中,复杂度为O(n),再用一个O(n)的时间复杂度从哈希表中查找即可。
三数之和思路
还是运用双指针的思想,这回不是快慢指针的思想了。
- 首先考虑数组长度小于3的,直接返回null
- 对数组进行排序
- 遍历排序后的数组
当前nums[i]>0,后面的数就都大于0了,于是直接break;
跳过重复元素,避免重复解
令左指针=i+1,右指针=n-1,在L<R的情况下进行循环
nums[i]+nums[L]+nums[R]==0时,判断L++和R–是否和之前的一样,不同的话就返回
如果nums[i]+nums[L]+nums[R]>0,则右指针的值太大,R–
如果nums[i]+nums[L]+nums[R]<0,则左指针的值太小,L++
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
if (nums.size()<3) return ans;
sort(nums.begin(), nums.end());
if (nums[0]>0) return ans;
int i = 0;
while (i<nums.size()) {
int left = i + 1, right = nums.size() - 1;
while (left< right) {
if (nums[i]>0) break;
// 转换为long long避免加法过程中溢出
long long y = static_cast<long long>(nums[i]);
long long x = static_cast<long long>(nums[left]);
long long z = static_cast<long long>(nums[right]);
if (x + y >0 - z)
right--;
else if (x + y <0 - z)
left++;
else {
ans.push_back({ nums[i], nums[left], nums[right] });
// 相同的left和right不应该再次出现,因此跳过
while (left<right&&nums[left] == nums[left + 1])
left++;
while (left<right&&nums[right] == nums[right - 1])
right--;
left++;
right--;
}
}
// 避免nums[i]作为第一个数重复出现
while (i + 1<nums.size() && nums[i] == nums[i + 1])
i++;
i++;
}
return ans;
}
};
启发是对数组进行排序,就可以根据和来调整左右指针了,并且对正值后面都不用判断了省了不少时间!