【刷题day6】哈希表| 242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和

文章讨论了几种常见的编程问题的解决方案,包括检查两个字符串是否为字母异位词、找出两个整数数组的交集以及判断快乐数的方法。在解决这些问题时,使用了哈希表(如unordered_map和unordered_set)来优化查找效率,以及双指针技巧来处理数组。在字母异位词问题中,通过计数字符出现的次数来判断;在交集问题中,利用集合去重;在快乐数问题中,检测数字求和的循环状态。
摘要由CSDN通过智能技术生成

242. 有效的字母异位词

自己的想法
 bool isAnagram(string s, string t) {
        unordered_map<char,int>st1,st2;
        for(char &ch: s){
            st1[ch]++;
        }
        for(char &ch: t){
            st2[ch]++;
        }
        if(st1.size()!=st2.size()){
            return false;
        }
        for(int i=0;i<st1.size();i++){
            if(st1[i]==st2[i]){
                continue;
            }
            else{
                return false;
            }
        }
        return true;
    }
代码随想录的想法
    bool isAnagram(string s, string t) {
        int record[26] = {0};//使用数组表示哈希表 大小为26 ,初始化为0,字符a映射为0,字符z映射为25
        for (int i = 0; i < s.size(); i++) {//将s中字符出现的次数统计在数组中
            record[s[i] - 'a']++;
        }
        for (int i = 0; i < t.size(); i++) {//t中字符出现一次就减少一次
            record[t[i] - 'a']--;
        }
        for (int i = 0; i < 26; i++) {
            if (record[i] != 0) {//如果有的元素不为零0,说明字符串s和t 一定是谁多了字符或者谁少了字符。
                return false;
            }
        }
        return true;// record数组所有元素都为零0,说明字符串s和t是字母异位词
    }

349. 两个数组的交集

使用count,返回的是被查找元素的个数。如果有,返回1;否则,返回0。注意,map中不存在相同元素,所以返回值只能是1或0。使用find,返回的是被查找元素的位置,没有则返回map.end()。
 vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_map<int,int>s1,s2;
        vector<int> res;
        for(int &x:nums1){
            s1[x]++;
        }
        for(int &x:nums2){
            s2[x]++;
        }
        for(auto it=s1.begin();it!=s1.end();it++)
        {
            if(s2.count(it->first)){//用count不用find?
                res.push_back(it->first);
            }
        }
        return res;
    }
代码随想录
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; // 存放结果,之所以用set是为了给结果集去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int num : nums2) {
            // 发现nums2的元素 在nums_set里又出现过
            if (nums_set.find(num) != nums_set.end()) {//下标不是最后的 说明找到了
                result_set.insert(num);
            }
        }
        return vector<int>(result_set.begin(), result_set.end());//将哈希表转换为数组的形式
    }

202. 快乐数

题目中说了会 无限循环,那么也就是说 求和的过程中,sum会重复出现,如果重复了就是return false, 否则一直找到sum为1为止。
unordered_set<int> set;
   bool isHappy(int n) {
        unordered_set<int> set;
        while(1) {
            int sum = 0;
            while (n) {
                sum += (n % 10) * (n % 10);
                n /= 10;
            }
            if (sum == 1) {
                return true;
            }
            
            if (set.count(sum)) {// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
                return false;
            } 
            else {
                set.insert(sum);
            }
            n = sum;//忘记更新
        }
    }
unordered_map<int,int> set;
    bool isHappy(int n) {
        unordered_map<int,int> set;
        while(1) {
            int sum = 0;
            while (n) {
                sum += (n % 10) * (n % 10);
                n /= 10;
            }
            if (sum == 1) {
                return true;
            }
            
            if (set.count(sum)) {// 如果这个sum曾经出现过,说明已经陷入了无限循环了,立刻return false
                return false;
            } 
            else {
                set[sum]++;
            }
            n = sum;//忘记更新
        }
    }

1. 两数之和

错误解法:看到求两数字之和首先想到的是“方向相反的两个指针经常用于求排序数组两数之和”,于是想到先排序再使用双指针。但是存在一个问题:返回的下标是经过排序后的下标,于是需要一个数据结构记录这个映射。我选择的是哈希表,使用哈希表记录这个映射的话,是不允许有重复元素的;或者说,有新的重复元素是会将原来映射覆盖的,于是有些测试用例便跑不过。
vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int>s;//允许重复 但是重复元素 是覆盖的
        for(int i=0;i<nums.size();i++){//key数值  value数组的下标
            s[nums[i]]=i;
        }
        sort(nums.begin(),nums.end());
        int left=0,right=nums.size()-1;
        while(left<right){
            if(nums[left]+nums[right]>target){
            right--;
            }
            else if(nums[left]+nums[right]<target){
                left++;
            }
            else{
                //return {left,right};//但是这个时候返回的是经过排序后数组的下标 所以要想使用这个方法需要一个原数组与现在数组的一个映射
                if(s.count(nums[left])&&s.count(nums[right])){
                    return {s[nums[left]],s[nums[right]]};
                }
            }
        }
    return {-1,-1};  
    }
双指针正确写法
    vector<int> twoSum(vector<int>& nums, int target) {
        vector<pair<int, int>> arr(nums.size());//将数组的数值与其下标以数值对的形式存储在容器中
        int  l = 0, r = nums.size() - 1;
        for(int i=0;i<nums.size();i++) 
            arr[i] = {nums[i], i};
        sort(arr.begin(), arr.end());
        while(l<r){
            if(arr[l].first + arr[r].first < target) 
                l++;
            else if(arr[l].first + arr[r].first > target) 
                r--;
            else 
                return {arr[l].second, arr[r].second};
        }
        return {};
    }
代码随想录
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map <int,int> map;//存放遍历过的元素
        for(int i = 0; i < nums.size(); i++) {
            // 遍历当前元素,并在map中寻找是否有匹配的key
            auto iter = map.find(target - nums[i]); //要查询的值的下标
            if(iter != map.end()) {//出现过
                return {iter->second, i};
            }
            // 如果没找到匹配对,就把访问过的元素和下标加入到map中
            map.insert(pair<int, int>(nums[i], i)); 
        }
        return {};
    }
哈希表比较擅长给你一个元素,判断在这个集合里是否出现过
使用数组表示哈希表的情况是:key有限且比较少
使用set的情况是:数值分布很分散
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值