leetcode——哈希汇总:leetcode 1002. 查找共用字符 leetcode 349. 两个数组的交集 leetcode 202. 快乐数 JZ75 字符流中第一个不重复的字符 leet


参考自: https://gitee.com/programmercarl/leetcode-master/blob/master/problems/

前置知识点:

(1)哈希表都是用来快速判断一个元素是否出现集合里,但是牺牲了空间来换取时间,因为我们要使用额外的数组,set或者是map来存放数据,才能实现快速的查找。

(2)哈希碰撞的解决办法:

  • 拉链法:发生冲突的元素都被存储在链表中(选择适当的哈希表的大小,这样既不会因为数组空值而浪费大量内存,也不会因为链表太长而在查找上浪费太多时间)
  • 线性探测法:一定要保证tableSize大于dataSize,用哈希表中的其他的空位来解决碰撞问题

(3)使用哈希法来解决问题时,选择数组、set(集合)、map(映射)三种数据结构
在这里插入图片描述

leetcode 1002. 查找共用字符

https://leetcode-cn.com/problems/find-common-characters/在这里插入图片描述

参考自代码随想录的思路:
在这里插入图片描述

class Solution {
public:
    vector<string> commonChars(vector<string>& words) {
        map<char,int> hash;
        vector<string> res;
        // 给hash初始化
        for(int i=0;i<words[0].size();i++){
            hash[words[0][i]] ++;
        }
        // 遍历其他的单词
        for(int i=1;i<words.size();i++){
            // 初始化tmp
            map<char,int> tmp;
            for(int j=0;j<words[i].size();j++){
                tmp[words[i][j]] ++;
            }
            // 更新hash
            for(char i='a';i<='z';i++){
                if(tmp[i] < hash[i]) hash[i] = tmp[i];
            }
        }
        // 只要map中的value不为0就将key放入结果集中
        for(char i='a';i<='z';i++){
            while(hash[i]!=0){
                string a="";
                a+=(char)i;
                res.push_back(a);
                hash[i]--;
            }
        }
        return res;
    }
};

leetcode 349. 两个数组的交集

https://leetcode-cn.com/problems/intersection-of-two-arrays/
在这里插入图片描述
解:
在这里插入图片描述

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 必须用set使得结果中的元素唯一
        unordered_set<int> res;
        // 把nums1中的元素统计到tmp中,使得元素唯一
        unordered_set<int> tmp(nums1.begin(),nums1.end());
        for(int num : nums2){
            // 看tmp中有没有nums2中的元素,找到说明是重复元素
            if(tmp.find(num) != tmp.end()){ //找一遍后没有到末尾说明找到了
                res.insert(num);
            }
        }
        // 把unrodered_set中的元素放到vector中
        return vector<int>(res.begin(),res.end());
    }
};

leetcode 202. 快乐数

https://leetcode-cn.com/problems/happy-number/
在这里插入图片描述
不断地对结果各位取平方和,当和为1时返回true,当进入死循环说明sum的值出现过(用set记录)此时返回false

class Solution {
public:
    // 求n各位之和
    int getSum(int n){
        int i,sum=0;
        while(n!=0){
            i = n % 10;
            sum += i * i;
            n /= 10;
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1){
            int sum = getSum(n);
            if(sum == 1) return true;
            //出现在set中表示进入死循环
            if(set.find(sum) != set.end()){
                return false;
            }else{
                set.insert(sum);
            }
            n = sum;
        }
    }
};![请添加图片描述](https://img-blog.csdnimg.cn/bafdd782df97404cb1d750aeae5d402d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATmVmdV9seWg=,size_20,color_FFFFFF,t_70,g_se,x_16)

JZ75 字符流中第一个不重复的字符

https://www.nowcoder.com/practice/00de97733b8e4f97a3fb5c680ee10720
在这里插入图片描述
请添加图片描述

class Solution
{
public:
    queue<char> q;
    unordered_map<char,int> m;
  //Insert one char from stringstream
    void Insert(char ch) {
        //没有出现过,则放入队列中
         if(m.find(ch) == m.end()) q.push(ch);
        // 记录每个单词出现次数
         m[ch]++;
    }
  //return the first appearence once char in current stringstream
    char FirstAppearingOnce() {
        while(!q.empty()){
            char ch = q.front();
            if(m[ch]==1){
               return ch; 
            }else{
                q.pop();
            }
        }
        return '#';
    }
};

leetcode1. 两数之和

https://leetcode-cn.com/problems/two-sum/
在这里插入图片描述
在map里存<元素,元素下标>, 找当前元素的key是否在map中有值,有则返回当前的下标和互补数的下标。没有则将<元素,下标>存入map中

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> m;
        for(int i=0;i<nums.size();i++){
            auto iter = m.find(target - nums[i]);
            if(iter != m.end()) return {iter->second,i};
            m.insert({nums[i],i});
        }
        return {};
    }
};

两数之和不能使用双指针法,因为两数之和要求返回的是索引下标, 而双指针法一定要排序,一旦排序之后原数组的索引就被改变了。如果要求返回的是数值的话,就可以使用双指针法。

leetcode 15. 三数之和

https://leetcode-cn.com/problems/3sum/
在这里插入图片描述
用三个指针 i、l、r 分别指向当前遍历元素nums[i]、nums[i+1]、最后一个元素nums[nums.size()-1]

  • 当三者的和>0,r - -
  • 当三者的和<0,l - -
  • 当三者的和==0,将三个元素放入res,同时将与当前元素相同的值去除,收缩 l r 的查找范围
class Solution {
public:
    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) return res;
            // i相同只需要一个结果
            if (i > 0 && nums[i] == nums[i - 1]) { 
                continue;
            }

            int a = nums[i];
            int l = i + 1, r = nums.size() - 1;
            while(l<r){
                int b = nums[l], c = nums[r];
                if(a + b + c < 0) l ++;
                else if(a + b + c > 0) r --;
                else {
                    res.push_back({a,b,c});
                    while (l < r && nums[l] == nums[l + 1]) l++;
                    while (l < r && nums[r] == nums[r - 1]) r--;
                    //找到结果集时搜索范围变小
                    l++;
                    r--;
                }
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值