leetcode:15. 三数之和
题目
给你一个包含 n
个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0
且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
输入:nums = []
输出:[]
输入:nums = [0]
输出:[]
解答 & 代码
写法一:
class Solution {
private:
// 双指针法求两数之和
// 返回数组中所有和为 target 的两个数,要求不能重复。传入的 nums 是升序数组
vector<vector<int>> twoSum(vector<int>& nums, int start, int end, int target)
{
vector<vector<int>> result;
int left = start;
int right = end;
while(left < right)
{
int leftNum = nums[left];
int rightNum = nums[right];
int sum = leftNum + rightNum;
if(sum < target)
{
while(left < right && nums[left] == leftNum)
++left;
}
else if(sum > target)
{
while(left < right && nums[right] == rightNum)
--right;
}
else
{
result.push_back({leftNum, rightNum});
while(left < right && nums[left] == leftNum)
++left;
while(left < right && nums[right] == rightNum)
--right;
}
}
return result;
}
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
int targetSum = 0;
// 1. 先排序
sort(nums.begin(), nums.end());
int firstIdx = 0;
// 2. 穷举第一个数
while(firstIdx < nums.size())
{
int first = nums[firstIdx];
// 2.1 targetSum - 第一个数,求两数之和
vector<vector<int>> twoSumResult = twoSum(nums, firstIdx + 1, nums.size() - 1, targetSum - first);
for(int i = 0; i < twoSumResult.size(); ++i)
{
int second = twoSumResult[i][0];
int third = twoSumResult[i][1];
result.push_back({first, second, third});
}
// 跳过重复数字
while(firstIdx < nums.size() && nums[firstIdx] == first)
++firstIdx;
}
return result;
}
};
复杂度分析:
- 时间复杂度 O(
):
- 数组排序时间复杂度 O(N logN)
- 外层
while
循环遍历数组寻找第一个数first
,时间复杂度 O(N);循环里调用twoSumResult
用双指针法求两数之和,时间复杂度 O(N)。因此总体时间复杂度 O()
- 空间复杂度 O(N):
twoSumResult
存储两数之和的结果
执行结果:
执行结果:通过
执行用时:100 ms, 在所有 C++ 提交中击败了 28.65% 的用户
内存消耗:23.1 MB, 在所有 C++ 提交中击败了 11.28% 的用户