目录
454 四数相加
我们选择把四个数组两两分开,想把前两个数组的值相加以后,加到map容器里面,然后在后两个数组里面去找对应的值
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> m;
int result = 0; //记录有几个符合条件的结果
//我们先把前两个数组的值加起来到map里面,然后再去遍历后面两个
for (int i = 0; i < nums1.size(); i++) {
for (int j = 0; j < nums2.size(); j++) {
m[nums1[i] + nums2[j]]++; //键是num相加值,值则是他们出现的次数
}
}
for (int i = 0; i < nums3.size(); i++) {
for(int j = 0; j < nums4.size(); j++){
if (m.find(-(nums3[i] + nums4[j])) != m.end()) {//在m里面找有没有num3,4的相反数
result += m[-(nums3[i] + nums4[j])];//值相当于他们出现的次数,所以直接加上去
}
}
}
return result;
}
};
383 赎金信
这一题的思路和等效异位词一样,但是最后判断的条件不同,赎金信允许数组的值大于0
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
int arr[26] = {0};//数是有效且较小,所以用数组
//要注意magazine里面的字母是可以比ransomNote多
for(int i = 0; i < magazine.length(); i++){
arr[magazine[i] - 'a']++;
}
for(int j = 0; j < ransomNote.length(); j++){
arr[ransomNote[j] - 'a']--;
}
for(int i = 0; i < 26; i++){
//如果可以由magazine构成,那么数组里面的值不可能小于0
//如果由小于0说明ransomNote里面的字母比magazine要多九不能构成了
if(arr[i] < 0){
return false;
}
}
return true;
}
};
15 三数之和
用for循环先固定一个数,然后用双指针去找加起来等于0的数,重要的地方还有范围,因为3个数组太多了,因此,我们要找出一些特殊情况避免没必要循环浪费时间
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> v;
sort(nums.begin(), nums.end());
//有三个数,我们这里使用双指针的方法
for(int i = 0; i < nums.size(); i++){
//因为我们排好序了,如果第一个数大于0,后面的肯定大于0
if(nums[i] > 0) return v;
//如果第一个数的只和之前上一个只一样,那也不用比了,不然会重复
if(i > 0 && nums[i] == nums[i - 1]) continue;
int slow = i + 1;
int fast = nums.size() - 1;
while(slow < fast){
//如果三个数小于0,就让慢指针后移
if(nums[i] + nums[slow] + nums[fast] < 0){
slow++;
}else
//如果三个数大于0,就让快指针前移
if(nums[i] + nums[slow] + nums[fast] > 0){
fast--;
}else
//如果三个数等于0,就插到集合里面,然后让快慢指针都移动
{
v.push_back(vector<int>{nums[i], nums[slow], nums[fast]});
while(slow < fast && nums[slow] == nums[slow+1]) slow++;
while(slow < fast && nums[fast] == nums[fast-1]) fast--;
slow++;
fast--;
}
}
}
return v;
}
};
18 四数之和
思路和三数之和差不多,但特殊情况比三数之和更多,要多注意
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
//和三数之和一样,排序一下更好做
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size(); 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 < nums.size(); j++){
//如果前两个数大于target,直接跳过这个i的值了
if(nums[i] + nums[j] > target && nums[i] + nums[j] >= 0) {
break;
}
//如果前后两个值一样大,就continue跳过,进行下一个j下标
if(j > i + 1 && nums[j] == nums[j - 1]) {
continue;
}
int left = j + 1;
int right = nums.size() - 1;
while(left < right){
//大于目标值就--
if((long)nums[i] + nums[j] + nums[left] + nums[right] > target){
right--;
}else
//小于目标值就++
if((long)nums[i] + nums[j] + nums[left] + nums[right] < target){
left++;
}else{
result.push_back(vector<int>{nums[i], nums[j], nums[left], nums[right]});
while(left < right && nums[right] == nums[right - 1]) right--;
while(left < right && nums[left] == nums[left + 1]) left++;
left++;
right--;
}
}
}
}
return result;
}
};