454. 四数相加II
第一想法
two sum的变形,把数组两两分组之后变成two sum;
看完题解后的想法
——
实现中遇到的困难
这里最开始看到分组都要两层循环,时间复杂度达到 $O(n^2)$ ,就觉得在查询逻辑里可以不用哈希直接遍历,因为也是两层循环;
但是这个是要考虑数组大小的,原来的数组大小是 $n$ ,分组求和之后就是 $n^2$ ,如果再两层遍历循环这个 $n^2$ 的数组复杂度就是 $O(n^4)$ ;
代码
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> hash;
int cnt = 0;
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
hash[nums1[i] + nums2[j]]++;
}
}
for (int i = 0; i < nums3.size(); i++) {
for (int j = 0; j < nums4.size(); j++) {
int sum = nums3[i] + nums4[j];
if (hash.count(-sum) != 0) {
cnt += hash[-sum];
}
}
}
return cnt;
}
};
383. 赎金信
第一想法
类似于异构词,但是只用部分一致;
看完题解后的想法
——
实现中遇到的困难
——
代码
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int arr[26] = {0};
for (char c : magazine) {
arr[c - 'a']++;
}
for (char c : ransomNote) {
if (--arr[c - 'a'] < 0) {
return false;
} ;
}
return true;
}
};
15. 三数之和
第一想法
第一眼没看出来怎么做;
看完题解后的想法
需要先排序,然后定位第一个数,再去移动两个指针,并且三个指针都需要去重;
实现中遇到的困难
去重逻辑需要写在找到之后,不能写在外面,不然会漏解:
解的组成可能 l 和 r 指向的数是一样的,如果在找到解的外面去重,就会漏接;
代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size()-2; i++) {
if (i > 0 && nums[i] == nums[i-1]) {
continue;
} else {
int l = i + 1, r = nums.size() - 1;
while (l < r) {
int sum = nums[i] + nums[l] + nums[r];
if (sum < 0) {
l++;
} else if (sum > 0) {
r--;
} else {
result.push_back({nums[i], nums[l], nums[r]});
while (l < r && nums[l] == nums[l+1]) { // 走到最后一个重复位置
l++;
}
while (l < r && nums[r] == nums[r-1]) {
r--;
}
l++; // 往前走一格
r--;
}
}
}
}
return result;
}
};
18. 四数之和
第一想法
在三数和之上加一个坐标的移动;
K数和都是这种方法;
看完题解后的想法
——
实现中遇到的困难
因为数字很大,需要使用long;
并且直接nums.size()进行判断很容易出错,先转换为int好(因为size返回的是size_t);
代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
int n = nums.size();
for (int i = 0; i < n-3; i++) {
if (i > 0 && nums[i] == nums[i-1]) {
continue;
}
for (int j = i + 1; j < n - 2; j++) {
if (j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int l = j + 1, r = n - 1;
while (l < r) {
long sum = (long) nums[i] + nums[j] + nums[l] + nums[r];
if (sum < target) {
l++;
} else if (sum > target) {
r--;
} else {
result.push_back({nums[i], nums[j], nums[l], nums[r]});
while (l < r && nums[l] == nums[l+1]) { // 走到最后一个重复位置
l++;
}
while (l < r && nums[r] == nums[r-1]) {
r--;
}
l++; // 往前走一格
r--;
}
}
}
}
return result;
}
};
今日收获
学习了K数和的解题思路;