Leetcode 454 四数相加Ⅱ
unordered_map使用的练习,一次通过,但是定义了两个unordered_map,并且需要经过两次遍历,空间和时间消耗都增加了
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<long long ,int>m1;
unordered_map<long long ,int>m2;
int ans=0;
for(int i=0;i<nums1.size();++i)
{
for(int j=0;j<nums2.size();++j)
{
m1[nums1[i]+nums2[j]]++;
}
}
for(int i=0;i<nums3.size();++i)
{
for(int j=0;j<nums4.size();++j)
{
m2[nums3[i]+nums4[j]]++;
}
}
for(auto it1:m1)
{
for(auto it2:m2)
{
if(it1.first+it2.first==0)
{
ans+=it1.second*it2.second;
}
}
}
return ans;
}
看了代码随想录以后才明白一个unordered_map两次遍历就可以了,查找0-(c+d)即可
int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
unordered_map<int, int> umap; //key:a+b的数值,value:a+b数值出现的次数
// 遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中
for (int a : A) {
for (int b : B) {
umap[a + b]++;
}
}
int count = 0; // 统计a+b+c+d = 0 出现的次数
// 再遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就把map中key对应的value也就是出现次数统计出来。
for (int c : C) {
for (int d : D) {
if (umap.find(0 - (c + d)) != umap.end()) {
count += umap[0 - (c + d)];
}
}
}
return count;
}
Leetcode 383 赎金信
本来想采用数组来统计字母出现次数,但是由于ransomNote是magazine的子集,因此不能直接算arr中减为零的字母,考虑到子集的存在,并且magazine中一个字符只能使用一次,因此词用unordered_map<char,int>m统计magazine中字符出现次数,查找ransomNote中字符时,如果没有出现直接返回false,出现一次m[c]--,如果m[c]=0,直接删除该字符的key,如果ransomNote中还有c,那么就表明不能由magazine构成
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char,int>m;
for(char c:magazine)
{
m[c]++;
}
for(char c:ransomNote)
{
auto it=m.find(c);
if(it==m.end())
return false;
else
{
m[c]--;
if(m[c]==0)
{
m.erase(c);
}
}
}
return true;
}
Leetcode 15 三数之和
这道题考虑了一会没想出来怎么做,本来想要通过哈希表统计两两数之和,再计算第三个数,但是发现由于不重复的原因,查重处理起来很麻烦。看了随想录的思路是二分法后,尝试从这个方面进行编写,采用set<vector
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>ans;
set<vector<int>>check;
ranges::sort(nums);
int left=0;
int right=nums.size()-1;
for(int i=0;i<nums.size()-2;++i)
{
right=nums.size()-1;
left=i+1;
while(left<right)
{
if(nums[i]+nums[left]+nums[right]<0)
{
left++;
continue;
}
else if(nums[i]+nums[left]+nums[right]>0)
{
right--;
continue;
}
check.insert({nums[i],nums[left],nums[right]});
left++;
}
}
set<vector<int>>::iterator it;
for(it=check.begin();it!=check.end();++it)
{
ans.push_back(*it);
}
return ans;
}
Leetcode 18 四数之和
模仿三数之和进行,依然采用set<vector
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>>ans;
set<vector<int>>check;
if(nums.size()<4)
{
return ans;
}
ranges::sort(nums);
for(int i=0;i<nums.size()-3;++i)
{
if(nums[i]>target&&nums[i]>=0)
{
break;
}
//转化为三数之和
for(int j=i+1;j<nums.size()-2;++j)
{
int left=j+1;
int right=nums.size()-1;
while(left<right)
{
if((long)nums[i]+nums[j]+nums[left]+nums[right]<target)
{
left++;
}
else if((long)nums[i]+nums[j]+nums[left]+nums[right]>target)
{
right--;
}
else
{
check.insert({nums[i],nums[j],nums[left],nums[right]});
left++;
right--;
}
}
}
}
set<vector<int>>::iterator it;
for(it=check.begin();it!=check.end();++it)
{
ans.push_back(*it);
}
return ans;
}
运行结果不出所料地拉跨,执行用时和内存消耗双双垫底。
看了看随想录的代码。发现自己有对很多无关情况都进行了处理,例如nums[i]>target时,已经做不到=target,不需要考虑后面的数。由于对nums进行了排序,相邻的数字如果相等的话也不需要进行循环,直接移动到下一个位置即可,例如left增加过程中相同的nums[left]无需重复考虑
if (nums[k] > target && nums[k] >= 0) {
break; // 这里使用break,统一通过最后的return返回
}
// 对nums[k]去重
if (k > 0 && nums[k] == nums[k - 1]) {
continue;
}
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
浙公网安备 33010602011771号