【算法挨揍日记】day04——15. 三数之和、18. 四数之和

简介: 题目描述:给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

15. 三数之和

题目描述:

给你一个整数数组 nums判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != kj != 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
  • abcd互不相同
  • 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. };


相关文章
|
算法 索引
|
算法 索引
【算法挨揍日记】day09——35. 搜索插入位置、69. x 的平方根
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
84 0
|
算法 测试技术 容器
【算法挨揍日记】day02——双指针算法_快乐数、盛最多水的容器
题目: 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为:
63 0
|
算法
【算法挨揍日记】day12——153. 寻找旋转排序数组中的最小值、LCR 173. 点名
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:
115 1
|
算法
【算法挨揍日记】day06——1004. 最大连续1的个数 III、1658. 将 x 减到 0 的最小操作数
1004. 最大连续1的个数 III 题目描述: 给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。
411 1
|
算法
【算法挨揍日记】day10——704. 二分查找、34. 在排序数组中查找元素的第一个和最后一个位置
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
364 0
|
算法 索引
【算法挨揍日记】day08——30. 串联所有单词的子串、76. 最小覆盖子串
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words = [&quot;ab&quot;,&quot;cd&quot;,&quot;ef&quot;], 那么 &quot;abcdef&quot;, &quot;abefcd&quot;,&quot;cdabef&quot;, &quot;cdefab&quot;,&quot;efabcd&quot;, 和 &quot;efcdab&quot; 都是串联子串。 &quot;acdbef&quot; 不是串联子串,因为他不是任何 words 排列的连接。
389 0
|
存储 算法 索引
【算法挨揍日记】day07——904. 水果成篮、438. 找到字符串中所有字母异位词
题目描述: 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主人设定了
351 0
|
算法
【算法挨揍日记】day05——209. 长度最小的子数组、3. 无重复字符的最长子串
题目描述: 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
360 0
|
算法
【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字
【算法挨揍日记】day03——双指针算法_有效三角形的个数、和为s的两个数字
54 0