15. 三数之和
方法一:排序+左右双指针
用时:1h10m31s
思路
1)排序:首先对数组进行排序。
2)双指针:定一找二。
设“三数”分别为a、b、c,依次遍历数组中的每个数字,作为a,即“定一”,注意移动a的过程时候要一直移动到不重复的数为止,防止结果重复;
然后对a右边的数组使用双指针,即“找二”,双指针的起始位置为a的右边第一个数b以及数组最后一个数c,双指针向中间走。如果当前三数之和小于0,则b向右移,因为数组排序过了,只有b向右移才有可能等于0;如果和大于0,则c向左移,理由类似;如果和等于0,则记录结果,并将b向右移,c向左移,注意此处需要一直移动到出现新的数字,以防结果重复。
- 时间复杂度: O ( n 2 ) O(n^2) O(n2)。
- 空间复杂度: O ( log n ) O(\log{n}) O(logn),排序需要的空间。
C++代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int size = nums.size();
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < size - 2; ++i) {
// 如果第一个数字都大于0,那么三数之和就不可能等于0
if (nums[i] > 0) return res;
// 防止出现重复的三元组
if (i > 0 && nums[i] == nums[i - 1]) continue;
int left = i + 1;
int right = size - 1;
while (left < right) {
int sum = nums[i] + nums[left] + nums[right];
if (sum < 0) ++left;
else if (sum > 0) --right;
else {
res.push_back({nums[i], nums[left], nums[right]});
while (left < right && nums[left] == nums[left + 1]) ++left;
while (left < right && nums[right] == nums[right - 1]) --right;
++left;
--right;
}
}
}
return res;
}
};
看完讲解的思考
注意去重。
代码实现遇到的问题
一开始被代码随想录坑了,想着用哈希表实现,结果搞了一个钟都搞不出来,这题感觉就不应该用哈希表来做啊!后面用双指针一下就做出来,不过做的时候还是有些小bug,忘记去重,结果要求是不重复的组合。
18. 四数之和
方法一:排序+左右双指针
用时:19m6s
思路
与上一题类似,多一层for循环
- 时间复杂度: O ( n 3 ) O(n^3) O(n3)。
- 空间复杂度: O ( log n ) O(\log{n}) O(logn)。
C++代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
int size = nums.size();
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < size - 3; ++i) {
// 如果第一个数已经大于target,则直接返回结果
if (nums[i] > target && nums[i] >= 0) break;
// 防止重复的四元组
if (i > 0 && nums[i] == nums[i - 1]) continue;
for (int j = i + 1; j < size - 2; ++j) {
// 同上
if (nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) break;
if (j > i + 1 && nums[j] == nums[j - 1]) continue;
int left = j + 1;
int right = size - 1;
while (left < right) {
long sum = (long) nums[i] + nums[j] + nums[left] + nums[right];
if (sum < target) ++left;
else if (sum > target) --right;
else {
res.push_back({nums[i], nums[j], nums[left], nums[right]});
// 去重
while(left < right && nums[left] == nums[left + 1]) ++left;
while(left < right && nums[right] == nums[right - 1]) --right;
++left;
--right;
}
}
}
}
return res;
}
};
看完讲解的思考
无。
代码实现遇到的问题
- 一开始其实想到了这么做,但是想着时间复杂度是 O ( n 3 ) O(n^3) O(n3),觉得不可能是最优解,想来想去想不到更好的解法,结果一看题解还真是这样。
- int溢出了,没有注意数组元素的取值范围,以后一定要注意!
344. 反转字符串
方法一:左右双指针
用时:2m
思路
左右双指针,交换。
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( 1 ) O(1) O(1)。
C++代码
class Solution {
public:
void reverseString(vector<char>& s) {
int left = 0;
int right = s.size() - 1;
while (left < right) swap(s[left++], s[right--]);
}
};
看完讲解的思考
无。
代码实现遇到的问题
无。
最后的碎碎念
21点才开始刷,结果整到了23点,溜了溜了。