15. 三数之和
题目描述:
给你一个整数数组 nums
,判断是否存在三元组 [nums[i], nums[j], nums[k]]
满足 i != j
、i != k
且 j != k
,同时还满足 nums[i] + nums[j] + nums[k] == 0
。请你返回所有和为 0
且不重复的三元组。
解题思路:
我们先来看看题目:题目要求a+b+c=0,并且a、b、c三个数的下标各不相同,并且返回所有的可能性,并且要去重
我们首先可以确定一下大体思路:sort排序(有序),有序可以被双指针或者二分来运用,这里我们使用排序+双指针
我们这里是三数之和,我们可以确定一个cur下标来遍历数组,一次一个数,然后问题就变成了剩下的数组的两数之和的问题!
我们两数之和就可以就可以运用双指针来降时间复杂度,left和right从两边到中间
这里比较考察大家的是left和right的边界问题,这里非常容易越界!!!
我们来结合本题的部分代码来理解
我们整个红色区域可以划分为[begin,right](这里就不用left和right避免混乱,这里的begin代表红色的第一个,end是红色区域的最后一个的下一个),我们正常来说left<end,right>0的,但是我们这边下标访问涉及到left+1和right-1,所以left需要比end少一,也就是让left+1最大到end-1的位置,同理right>1
解题代码:
1. class Solution { 2. public: 3. vector<vector<int>> threeSum(vector<int>& nums) { 4. sort(nums.begin(), nums.end()); 5. vector<vector<int>> nnums; 6. int size = nums.size(); 7. int cur = 0; 8. while (cur < size - 1) 9. { 10. int left = cur + 1; 11. int right = size - 1; 12. int a = (-1) * nums[cur];//找到两数之和为a的两个值 13. while (left < right) 14. { 15. if (nums[left] + nums[right] == a) 16. { 17. nnums.push_back({ nums[cur],nums[left],nums[right] }); 18. while (right > 1 && nums[right] == nums[right - 1]) 19. right--; 20. right--; 21. } 22. else if (nums[left] + nums[right] > a) 23. { 24. while (right > 1 && nums[right] == nums[right - 1]) 25. right--; 26. right--; 27. } 28. else if (nums[left] + nums[right] < a) 29. { 30. while (left<size-1&&nums[left] == nums[left + 1]) 31. left++; 32. left++; 33. } 34. } 35. while (cur<size-1&&nums[cur] == nums[cur + 1]) 36. cur++; 37. cur++; 38. 39. } 40. return nnums; 41. } 42. };
18. 四数之和
题目描述:
给你一个由 n
个整数组成的数组 nums
,和一个目标值 target
。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]]
(若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < n
a
、b
、c
和d
互不相同nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。
解题思路:
本题与上题一样,就是在三数之和的基础上外面再套一层
解题代码:
1. class Solution { 2. public: 3. vector<vector<int>> fourSum(vector<int>& nums, int target) { 4. sort(nums.begin(), nums.end()); 5. int size = nums.size(); 6. vector<vector<int>>nnums; 7. for (int i = 0; i < nums.size();) 8. { 9. int cur = i+1; 10. while (cur < size - 1) 11. { 12. int left = cur + 1; 13. int right = size - 1; 14. long long a = (long long)target-nums[i] - nums[cur];//找到两数之和为a的两个值 15. while (left < right) 16. { 17. if (nums[left] + nums[right] == a) 18. { 19. nnums.push_back({ nums[i],nums[cur],nums[left],nums[right] }); 20. while (right > 1 && nums[right] == nums[right - 1]) 21. right--; 22. right--; 23. } 24. else if (nums[left] + nums[right] > a) 25. { 26. while (right > 1 && nums[right] == nums[right - 1]) 27. right--; 28. right--; 29. } 30. else if (nums[left] + nums[right] < a) 31. { 32. while (left < size - 1 && nums[left] == nums[left + 1]) 33. left++; 34. left++; 35. } 36. } 37. while (cur < size - 1 && nums[cur] == nums[cur + 1]) 38. cur++; 39. cur++; 40. } 41. 42. while (i < size - 1 && nums[i] == nums[i + 1]) 43. i++; 44. i++; 45. } 46. return nnums; 47. } 48. };