leetcode刷题笔记_哈希表1

哈希表

设计哈希表

设计哈希集合

#define MAX_LEN 100000          // 初始化桶的数量

class MyHashSet {
private:
    vector<int> set[MAX_LEN];   // 使用数组实现哈希集合
    
    /** 返回对应的桶的索引 */
    int getIndex(int key) {
        return key % MAX_LEN;
    }
    
    /** 在特定的桶中搜索键,如果该键不存在则返回 -1 */
    int getPos(int key, int index) {
        // 每个桶中包含一个列表,遍历所有桶中的元素来寻找特定的键
        for (int i = 0; i < set[index].size(); ++i) {
            if (set[index][i] == key) {
                return i;
            }
        }
        return -1;
    }
public:
    
    MyHashSet() {
        
    }
    
    void add(int key) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
            // 如果键不存在,则添加
            set[index].push_back(key);
        }
    }
    
    void remove(int key) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos >= 0) {
            // 如果键存在,则删除
            set[index].erase(set[index].begin() + pos);
        }
    }
    
    bool contains(int key) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        return pos >= 0;
    }
};

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x79eft/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

设计哈希映射

#define MAX_LEN 100000            // 初始化桶的数量

class MyHashMap {
private:
    vector<pair<int, int>> map[MAX_LEN];       // 使用数组实现哈希集合
    
    /** 返回指定桶的索引 */
    int getIndex(int key) {
        return key % MAX_LEN;
    }
    
    /** 在桶中搜索键,如果不存在则返回 -1 */
    int getPos(int key, int index) {
        // 每个桶包含一个数组,遍历桶中的所有元素来查找指定的 key
        for (int i = 0; i < map[index].size(); ++i) {
            if (map[index][i].first == key) {
                return i;
            }
        }
        return -1;
    }
    
public:
    MyHashMap() {
        
    }
    
    /** value 始终为正 */
    void put(int key, int value) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
            map[index].push_back(make_pair(key, value));
        } else {
            map[index][pos].second = value;
        }
    }
    
    /** 如果存在映射关系,则返回 value,否则返回 -1 */
    int get(int key) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos < 0) {
            return -1;
        } else {
            return map[index][pos].second;
        }
    }
    
    /** 如果存在 key 的映射,则删除该映射关系 */
    void remove(int key) {
        int index = getIndex(key);
        int pos = getPos(key, index);
        if (pos >= 0) {
            map[index].erase(map[index].begin() + pos);
        }
    }
};
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x79eft/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

哈希集合

哈希集合的操作
#include <unordered_set>               

int main() {
    // 1. 初始化哈希集
    unordered_set<int> hashset;   
    // 2. 新增键
    hashset.insert(3);
    hashset.insert(2);
    hashset.insert(1);
    // 3. 删除键
    hashset.erase(2);
    // 4. 查询键是否包含在哈希集合中
    if (hashset.count(2) <= 0) {
        cout << "键 2 不在哈希集合中" << endl;
    }
    // 5. 哈希集合的大小
    cout << "哈希集合的大小为: " << hashset.size() << endl; 
    // 6. 遍历哈希集合
    for (auto it = hashset.begin(); it != hashset.end(); ++it) {
        cout << (*it) << " ";
    }
    cout << "在哈希集合中" << endl;
    // 7. 清空哈希集合
    hashset.clear();
    // 8. 查看哈希集合是否为空
    if (hashset.empty()) {
        cout << "哈希集合为空!" << endl;
    }
}

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x79eft/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
哈希集合查重
/*
 * 使用哈希集合寻找重复元素的模板
 */
bool findDuplicates(vector<Type>& keys) {
    // 将 type 替换为 keys 的实际类型
    unordered_set<Type> hashset;
    for (Type key : keys) {
        if (hashset.count(key) > 0) {
            return true;
        }
        hashset.insert(key);
    }
    return false;
}
作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x79eft/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

哈希映射

哈希表的操作

#include <unordered_map>                

int main() {
    // 1. 初始化哈希表
    unordered_map<int, int> hashmap;
    // 2. 插入一个新的(键,值)对
    hashmap.insert(make_pair(0, 0));
    hashmap.insert(make_pair(2, 3));
    // 3. 插入一个新的(键,值)对,或者更新值
    hashmap[1] = 1;
    hashmap[1] = 2;
    // 4. 获得特定键对应的值
    cout << "The value of key 1 is: " << hashmap[1] << endl;
    // 5. 删除键
    hashmap.erase(2);
    // 6. 检查键是否存在于哈希表中
    if (hashmap.count(2) <= 0) {
        cout << "键 2 不在哈希表中" << endl;
    }
    // 7. 哈希表的大小
    cout << "哈希表的大小为: " << hashmap.size() << endl; 
    // 8. 遍历哈希表
    for (auto it = hashmap.begin(); it != hashmap.end(); ++it) {
        cout << "(" << it->first << "," << it->second << ") ";
    }
    cout << "在哈希表中" << endl;
    // 9. 清空哈希表
    hashmap.clear();
    // 10. 检查哈希表是否为空
    if (hashmap.empty()) {
        cout << "哈希表为空!" << endl;
    }
}

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x79eft/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x7ejcs/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        map<int,int> mp;
        for(int i=0;i<nums.size();i++)
        {
            if(mp.count(target-nums[i])==0)
                mp[nums[i]]=i;
            else
                return{i,mp[target-nums[i]]};
        }
        return {};

    }
};

同构字符串

给定两个字符串 s 和 t,判断它们是否是同构的。

如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。

每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x7oyyd/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    bool isIsomorphic(string s, string t) {
        map<char,char> mp;
        //用于查看哈希表中已存在哪些字符
        map<char,int>value;
       
               
        for(int i=0;i<s.size();i++)
        {
             //遍历s和t中的字符,当s中的字符不在哈希表里时把s作为键,t作为值加入到哈希表里
             //存储值的哈希表放入t中的值,如果大于1说明已经存放过,返回false
            if(mp.count(s[i])==0)
            {
                if(value[t[i]]!=0)
                    return false;
                value[t[i]]++;
                mp[s[i]]=t[i];

            }
                
            //否则,查询当前字符的映射是否和哈希表中的映射对应
            else{
            //不同的字符映射到同一个字符上返回false
            //当s的字符哈希映射后与当前字符不匹配返回false
                if(mp[s[i]]!=t[i])
                    return false;                
            }
        }
        return true;

        

    }
};

两个列表的最小索引总和

假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。

你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x7rs1h/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
        
        map<string,int> canteen;
        int len1=list1.size();
        int len2=list2.size();
        
        if(len1==0||len2==0)
            return {};

        for(int i=0;i<list1.size();i++)
        {
            //哈希表先存list1中的餐厅,映射关系为对应的下标,为区分零下标和初始值0,用下标+1
            canteen.insert(pair<string,int>(list1[i],i));
        }
        int indexMin=10000;
        //记录当前索引和对应的字符串
        map<int, vector<string>> indexSum;
        for(int i=0;i<list2.size();i++)
        {
            //然后遍历list2看有没有已经存在哈希表中的餐厅
            //如果有,看是不是最小索引和
            if(canteen.find(list2[i])!=canteen.end())
            {
                //索引和是两个列表的下标相加
                int index=canteen[list2[i]]+i;              
                if(index<=indexMin)
                {
                    indexMin=index;
                    indexSum[indexMin].push_back(list2[i]);
                }
                
               
                //res.push_back(list2[i]);  
            }
        }
             
        return indexSum[indexMin];

    }
};

存在重复元素Ⅱ

给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x7m3zm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        map<int,int> mp;
        for(int i=0;i<nums.size();i++)
        {
            //每次找到这个数字就先判断坐标是是不是满足条件
            if(mp.find(nums[i])!=mp.end())
                if(i-mp[nums[i]]<=k)
                    return true;
            //不满足就继续找
                mp[nums[i]]=i;
           

        }
        return false;
    }
};

替换后的最长重复字符

给你一个仅由大写英文字母组成的字符串,你可以将任意位置上的字符替换成另外的字符,总共可最多替换 k 次。在执行上述操作后,找到包含重复字母的最长子串的长度。

注意:字符串长度 和 k 不会超过 104。

作者:力扣 (LeetCode)
链接:https://leetcode-cn.com/leetbook/read/hash-table-plus/x7auk1/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

class Solution {
public:
    int characterReplacement(string s, int k) {
        //分别保存窗口的左边和右边的下标
        int res=0,left=0,right=0;
        map<char,int> mp;
        //保存当前窗口的相同字符最大长度
            int curMaxlen=INT_MIN;
        while(right<s.size())
        {           
            mp[s[right]]++;
            curMaxlen=max(curMaxlen,mp[s[right]]);
            //如果当前窗口的最大字符长度+可换字符的长度>=窗口长度说明满足题意
            if((curMaxlen+k)>=(right-left+1))
                right++;
            else{
                //如果不满足,整个窗口移动直到满足题意
                mp[s[left]]--;
                left++;
                right++;               
            }
        }
        //最终的长度就是窗口的长度-1
        return right-left;

    }
};

最大连续1的个数Ⅲ

给定一个由若干 01 组成的数组 A,我们最多可以将 K 个值从 0 变成 1 。

返回仅包含 1 的最长(连续)子数组的长度。

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        map<int,int> map;
        int left=0,right=0,res=0,oneSum=0;
    
        
        
        
        while(right!=nums.size())
        {
            //往右走,是1,当前窗口1的数量就+1
            if(nums[right]==1)
                oneSum++;
            //满足当前1的长度+可修改长度>=窗口的长度时,快指针继续走
            if(oneSum+k>=right-left+1)
                right++;
            else{
                //否则就移动窗口,并把看最左边那个元素是不是1,是1就把当前1的数量-1
                if(nums[left]==1)
                    oneSum--;
                //移动整个窗口
                left++;
                right++;
            }   
        }
        //最终滑动窗口的长度-1就是1的最长数组
        return right-left;

    }
};

至多包含两个不同字符的最长子串

给定一个字符串 *s* ,找出 至多 包含两个不同字符的最长子串 *t* ,并返回该子串的长度。

class Solution {
public:
    int lengthOfLongestSubstringTwoDistinct(string s) {
        //快慢指针指向的坐标值,不同字母的个数初始值为0
       int left=0,right=0,diff=0;
       map<char,int> repeatCount;
       while(right<s.size())
       {
           //没出现过,新字符+1
           if(repeatCount[s[right]]==0)
                diff++;
            repeatCount[s[right]]++;
            //新字符大于2,窗口左移
            if(diff>2)
            {
                repeatCount[s[left]]--;
                //最左边的字符只出现一次,左移之后新字符-1
                if(repeatCount[s[left]]==0)
                    diff--;
                left++;
               
            }
             right++;
       }
        return right-left;

    }
   
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值