前言
哈希表的进阶操作,更加多维的方式去思考哈希表在实际中的应用,但是我们需要判断这个操作的可行性,是否有更好的思路去解决这个问题!
题目链接
一、四数相加
思路:刚开始一看题目,我就只能想到N^4的时间复杂度,然后想着借鉴三数之和,四数之和的思路,去固定数去找其他数,但是人家在一个数组容器里面,接着看题解,没想到还可以用哈希表来暂存中间的变量,达到用o^2的空间去换o^2的时间的目的,
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int>umap;
for(int a:nums1){
for(int b:nums2){
umap[a+b]++;
}
}
int count=0;
for(int c:nums3){
for(int d:nums4){
if(umap.find(0-(c+d))!=umap.end()){
count+=umap[0-(c+d)];
}
}
}
return count;
}
二、赎金信
思路:和字母异位的思路是一样的,只不过,这次改了一个逻辑点就是判断一下是否小于0.
bool canConstruct(string ransomNote, string magazine) {
int ans[26];
for(auto i:magazine){
ans[i-'a']++;
}
for(auto i:ransomNote){
ans[i-'a']--;
if(ans[i-'a']<0) return false;
}
return true;
}
三、三数之和
思路:定义结果集,然后排序使用双指针操作,主要是去固定数据,这里主要是想引入哈希的方法去去重,这个思路是没有问题的,不过实现的逻辑有点复杂。主流方法还是双指针。
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>res;
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size();i++){
if(nums[i]>0)break;
if(i>0&&nums[i]==nums[i-1])continue;
unordered_set<int>set;
for(int j=i+1;j<nums.size();j++){
if(j>i+2&&nums[j]==nums[j-1]&&nums[j-1]&&nums[j-2])continue;
int c=0-(nums[i]+nums[j]);
if(set.find(c)!=set.end()){
res.push_back({nums[i],nums[j],c});
set.erase(c);
}else{
set.insert(nums[j]);
}
}
}
return res;
}
//双指针的做法
vector<vector<int>> threeSum(vector<int>& nums) {
ranges::sort(nums);
vector<vector<int>>ans;
int n=nums.size();
for(int i=0;i<n;i++){
int x=nums[i];
if(nums[i]>0)break;
if(i&&x==nums[i-1])continue;
int j=i+1,k=n-1;
while(j<k){
int s=x+nums[j]+nums[k];
if(s>0)k--;
else if(s<0)j++;
else {
ans.push_back({x,nums[j],nums[k]});
while(j++,j<k&&nums[j]==nums[j-1]);j++;
while(k--,k>j&&nums[k]==nums[k+1]);k--;
}
}
}
return ans;
}
四、四数之和
思路:同理,这里直接介绍双指针的做法吧
vector<vector<int>> fourSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());//排序
vector<vector<int>> ret;//结果
int n=nums.size();//长度
for(int i=0;i<n;){
for(int j=i+1;j<n;){
int left=j+1,right=n-1;
long long aim=(long long)target-nums[i]-nums[j];
while(left<right){
int sum =nums[left]+nums[right];
if(sum<aim)left++;
else if(sum>aim)right--;
else{
ret.push_back({nums[i],nums[j],nums[left++],nums[right--]});
while(left<right&&nums[left]==nums[left-1])left++;
while(left<right&&nums[right]==nums[right+1])right--;
}
}
j++;
while(j<n&&nums[j]==nums[j-1])j++;
}
i++;
while(i<n&&nums[i]==nums[i-1])i++;
}
return ret;
}
总结
哈希表的主要用法就是去重,牺牲空间建立索引去直接查找一个数!,希望兄弟们在接着刷题的过程中,能结合前面的一些方法形成自己的做题技巧。