一、题目:
三数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
示例 1:
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
二、题解:1.解读
已知目标值,遍历数据找出两个数,且和为目标值。首先想到的就是暴力求解,也可以排序后二分,更好的方法也可以用Hash求解。
2.思路1
在思考两数之和解决方法的时候,我们使用了两层循环把所有的结果给求出来,相信大家很快就想到三数之和我就用三个循环,很棒,思路是一样,只是之前的a+b=0,现在的b=c+d了。好了代码呈上。
3.思路2
- 第一步将整个数组排序
<!---->
- 从左侧开始,选定第一个数为定值比如下面的-4,然后左右指针分别指向对应位置如下图,是不是很像快排。
<!---->
- 定义的左右和定值相加
- 如果等于0,记录下三个值
- 如果小于0,左指针右移动
- 如果大于0,右指针左移
- 然后定值右移,重复这个步骤
4.实现
在前面的两数之和的基础上,将目标值移动到左边等于0就转换为了上一次的练习题。二第二种方式采用先排队,然后两边夹击的方式求解。
三、代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
//int result[]={0.1};
int i= 0;
int j=0;
for(i;i<nums.size()-1;i++)
{
for(j=i+1;j<nums.size();j++)
{
if(nums[i]+nums[j]==target)//numb i + numbs[j] - target = 0
{
return {i,j};
}
}
}
return {i,j};
}
};
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int target;
vector<vector<int>> ans;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
if (i > 0 && nums[i] == nums[i - 1]) continue;
if ((target = nums[i]) > 0) break;
int left = i + 1, right = nums.size() - 1;
//取出三个数 所以不用left=right
while (left < right) {
if (nums[left] + nums[right] + target < 0) ++left;
else if (nums[left] + nums[right] + target > 0) --right;
else {
ans.push_back({target, nums[left], nums[right]});
++left, --right;
//去重
//测试数据[-2,0,0,2,2]
while (left < right && nums[left] == nums[left - 1]) ++left;
while (left < right && nums[right] == nums[right + 1]) --right;
}
}
}
return ans;
}
};
时间复杂度:O(n ^ 2)
空间复杂度:O(n)
四、总结
文中使用了两种方式来解决这个问题,第一种为复杂度较高的暴力解答,第二种使用了类似快排思想的双指针法,后面还会有更多关于双指针的用法,敬请期待。至此,想想有学会点什么了?