字符串字符完成hash 整数数组用set完成hash
四数相加II
法1: 创建2个map<int,int> 并比较
map<int,int>getMap(vector<int>& nums1, vector<int>& nums2){
map<int,int> s1;//key:和值, val:得到该和值的对数
for (int i = 0; i < nums1.size(); ++i) {
for (int j = 0; j < nums2.size(); ++j) {
int add = nums1[i]+nums2[j];
// s1.insert(make_pair(nums1[i]+nums2[j],k++));
if (s1.find(add) != s1.end()) s1[add]++;
else s1.insert(pair<int, int>(add, 1));
}
}
return s1;
}
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
//前两个数组的元素和 取相反数即为理想元组后两个数组的特定元素和
map<int,int> s1=getMap( nums1, nums2);
map<int,int> s2=getMap( nums3, nums4);
//
map<int,int>::iterator it;
//c++ 98
int ans=0;
for(it = s1.begin();it != s1.end();it++){
if (s2.find(-(it->first)) !=s2.end()) {
int val2 = s2[-(it->first)];
ans += (it->second) * val2;
}
}
return ans;
// //c++ 11
// for (const auto &item: s1)
}
时间和空间复杂度需要完善
判断字符串的子集
383. 赎金信
法1: 创建2个vector存放字符串的char-‘a’ 在vectormag中查找vectorrans的元素
bool canConstruct(string ransomNote, string magazine) {
if (ransomNote.length() > magazine.length())
return false;
vector<int>ran(26);
vector<int>mag(26);
for (int i = 0; i < magazine.length(); ++i) {
mag[magazine[i] - 'a']++;
}
for (int i = 0; i < ransomNote.length(); ++i) {
mag[ransomNote[i] - 'a']--;
if ( mag[ransomNote[i] - 'a'] < 0){
return false;
}
}
return true;
}
法2:创建2个map<int,int>mag存放string char - ‘a’ ,int num num是char出现的次数
耗时且占内存
/* map<int,int> mag=getMap(magazine);
map<int,int> ran=getMap(ransomNote);
// map<int,int>::iterator it;
for (const auto &it: ran){
if (mag.find(it.first) != mag.end()){
if (it.second > mag[it.first])
{
return false;
}
} else if (mag.find(it.first) == mag.end()){
return false;
}
}
return true;
}*/
三数之和
法1: 双指针解法
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
if (nums[0] > 0) return ans;
int len = nums.size();
for (int i = 0; i < len; ++i) {
int target = -nums[i];
if (i > 0 && nums[i] == nums[i-1])continue;
int k = len-1;
for (int j = i+1; j < len; ++j) {
if (j > i+1 && nums[j] == nums[j-1])continue;
while (j < k && nums[j] + nums[k] > target)
k--;
if (j == k) break;
if (nums[j] + nums[k] == target){
ans.push_back({nums[i], nums[j], nums[k]});
}
}
}
return ans;
}
法2:hash解法
vector<vector<int>> threeSum(vector<int>& nums) {
//hash法 Time Limit Exceeded
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
if (nums[0] > 0) return ans;
int len = nums.size();
for (int i = 0; i < len; ++i) {
if (i > 0 && nums[i] == nums[i-1])continue;
unordered_set<int> set;
for (int j = i+1; j < len; ++j) {
if (j > i + 2 && nums[j] == nums[j-1] && nums[j - 1] == nums[j-2])continue;// 三元组元素b去重
int target = -(nums[i] + nums[j]);
if (set.find(target) != set.end()){
ans.push_back({nums[i],nums[j],target});
set.erase(target); // 三元组元素c去重
} else{
set.insert(nums[j]);
}
}
}
return ans;
}
四数之和
法1:
思路 双指针借鉴三数字之和思路
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
int len = nums.size();
//大错有仨 1.遍历范围2.约束条件3.while循环写法
for (int i = 0; i < len-3; ++i) {
//约束条件 1
if (i > 0 && nums[i] == nums[i-1]) continue;
if ((long)nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
if ((long)nums[i] + nums[len - 3] + nums[len - 2] +nums[len - 1] < target) continue;
for (int j = i+1; j < len-2; ++j) {
int l = j + 1, r = len - 1 ;
//约束条件 2
if (j > i + 1 && nums[j] == nums[j-1]) continue;
if ((long)nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
if ((long)nums[i] + nums[j] + nums[len - 2] +nums[len - 1] < target) continue;
while (l < r){
long sum = (long)nums[i] + nums[j] + nums[l] + nums[r];
if (sum == target) {
ans.push_back({nums[i], nums[j], nums[l], nums[r]});
while(l < r && nums[l] == nums[l + 1]){
l++;
}
l++;
while(l < r && nums[r] == nums[r - 1]){
r--;
}
r--;
} else if (sum > target){
r--;
} else{
l++;
}
}
}
}
return ans;
}