454
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
map<int, int> m;
for (int i:nums1) {
for (int j:nums2) {
m[i+j]++;
}
}
int count=0;
for(int l:nums3) {
for (int k:nums4) {
if (m.find(-l-k)!=m.end()) {
count+=m[-l-k];
}
}
}
return count;
}
};
用两数之和的逻辑,把前两个数组遍历放在一起,后两个放在一起。value是出现的次数。
383
class Solution {
public:
bool canConstruct(string ransomNote, string magazine) {
if (ransomNote.length() > magazine.length()) {
return false;
}
int record[26] = {0};
for (int i=0; i<magazine.length(); i++) {
record[magazine[i]-'a']++;
}
for (int i=0; i<ransomNote.length(); i++) {
if(record[ransomNote[i]-'a']<=0) {
return false;
}
record[ransomNote[i]-'a']--;
}
return true;
}
};
用一个数组来记录出现的字母次数。
15
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() && nums[i]<=0; i++) {
if (i!=0 && nums[i] == nums[i-1]) {
continue;
}
int left = i+1;
int right = nums.size()-1;
while (left<right && nums[right]>=0) {
if (nums[i]+nums[left]+nums[right] == 0) {
vector<int> array;
array.push_back(nums[i]);
array.push_back(nums[left]);
array.push_back(nums[right]);
result.push_back(array);
while(left<right && nums[left+1]==nums[left]) {
left++;
}
while(right>left && nums[right-1] == nums[right]){
right--;
}
left++;
right--;
}
else if (nums[i]+nums[left]+nums[right] > 0) {
while(right>left && nums[right-1] == nums[right]){
right--;
}
right--;
}
else if (nums[i]+nums[left]+nums[right] < 0) {
while(left<right && nums[left+1]==nums[left]) {
left++;
}
left++;
}
}
}
return result;
}
};
重点在去重和双指针。
去重:判断条件是目前新的index位置和已经测试过的上一个是否一样,不要去判断下一个与现在的是否一样 容易出错。
双指针:对第一个元素遍历,对第二三个用双指针从i+1和末尾两端收缩。
18
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> result;
if (nums.size()<4) {
return result;
}
sort(nums.begin(), nums.end());
for (int i=0; i<nums.size()-3; i++) {
if (i!=0 && nums[i] == nums[i-1]) {
continue;
}
if (nums[i]>target && nums[i]>=0) {
break;
}
for (int j=i+1; j<nums.size()-2; j++) {
if (j!=i+1 && nums[j] == nums[j-1]) {
continue;
}
if (nums[i]+nums[j]>target && nums[j]>=0) {
break;
}
int left = j+1;
int right = nums.size()-1;
while(left<right) {
if ((long)nums[i]+nums[j]+nums[left]+nums[right] == target) {
vector<int> array;
array.push_back(nums[i]);
array.push_back(nums[j]);
array.push_back(nums[left]);
array.push_back(nums[right]);
result.push_back(array);
while (left<right && nums[left+1] == nums[left]) {
left++;
}
while (left<right && nums[right-1] == nums[right]) {
right--;
}
left++;
right--;
}
else 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++;
}
}
}
}
return result;
}
};
counter cases:
1.数组元素个数少于4直接return
2. [0,0,0,1000000000,1000000000,1000000000,1000000000] 1000000000
直接加会出现overflow 记得用(long)就可以解决了
思路:跟三数之和一样,不过第一二个元素用两个for loop遍历,第三四个用双指针。
因为target不一定是0所以剪枝的时候要判断 if (nums[i]>target && nums[i]>=0)