代码随想录Day6 | 哈希表01-leetcode242、349、202、1

242-有效的字母异位词

题目链接:有效的字母异位词

1.排序

算法描述:对字符串s和t进行排序后就可以直接比较排序后的字符串是否相等。

class Solution {
public:
    bool isAnagram(string s, string t) {
        //排序解法
        bool result = false;

        if(s.length() != t.length()){
            return result;
        }

        sort(s.begin() , s.end());
        sort(t.begin() , t.end());

        if(s == t)
            result = true;

        return result;
    }
};

时间复杂度:C++中提供的sort排序使用的是快速排序,时间复杂度为O(nlogn) 

2.数组结构的哈希表

算法描述:先遍历字符串s,使用哈希表记录每个字母出现的次数。再遍历字符串t,在哈希表中减去每个字母出现的次数。若哈希表每个元素都为0,则符合题意。

class Solution {
public:
    bool isAnagram(string s, string t) {
        // 哈希解法
        int hash[26] = {0};
        if(s.length() != t.length()){
            return false;
        }
        for(int i = 0; i < s.length(); i++){
            hash[s[i] - 'a']++;
        }
        for(int i = 0; i < t.length(); i++){
            hash[t[i] - 'a']--;
        }
        for(int i = 0; i< 26; i++){
            if(hash[i] != 0)
                return false;
        }
        return true;
    }
};

 时间复杂度:遍历字符串,因此时间复杂度为O(n)

空间复杂度:因为定义的是一个常量大小的辅助数组,所以空间复杂度为O(1)


349-两个数组的交集

题目链接:两个数组的交集

 思路:其实一上来的想法就是像上一道题一样使用数组结构的哈希表,但由于题目中nums中的数据范围较大,因此设置hash[1000]的数组可能会造成极大的空间浪费,因此放弃使用数组结构的哈希表。

1.set结构的哈希表

算法描述:将nums1转换成哈希表的形式存储,遍历nums2查找在哈希表中是否存在,存在则加入result。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        
        //set结构的哈希表
        unordered_set<int> result; // unordered_set中的数据不允许重复 直接利用数据结构去重
        unordered_set<int> nums_set(nums1.begin(), nums1.end());

        for(int num :nums2){
            if(nums_set.find(num) != nums_set.end())
                result.insert(num);
        }

        return vector<int>(result.begin(), result.end()); //强制类型转换
    }
};

 解题关键在于选择合适的数据结构:哈希表理论基础

2.暴力解法

算法描述:两层for循环遍历数组,若nums2中存在nums1中有的元素,则加入到result中。遍历完之后再通过排序去重。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        
        // 暴力解法
        vector<int> result;
        for(int i = 0; i< nums1.size(); i++){
            int number = nums1[i];
            for(int j = 0; j < nums2.size(); j++){
                if(nums2[j] == number){
                    result.push_back(number);
                    break;
                }
            }
        }

        // 排序后去重
        sort(result.begin(), result.end());
        result.erase(unique(result.begin(), result.end()), result.end());

        return result;
    }
};

3.排序+双指针(leetcode官方题解)

算法描述:先将nums1和nums2排序,使用双指针分别指向两个数组的起始位置。若指针指向的元素相等,则判断元素是否重复,不重复则加入result中,否则跳过。此时两个指针均向后移动。若nums1指针指向的元素小于nums2指针指向的元素,则nums1指针向后移。反之则nums2指针后移。

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        // 排序+双指针
        sort(nums1.begin(), nums1.end());
        sort(nums2.begin(), nums2.end());

        int len1 = nums1.size();
        int len2 = nums2.size();
        int p1 = 0, p2 = 0;

        vector<int> result;
        
        while(p1 < len1 && p2< len2){
            int num1 = nums1[p1], num2 = nums2[p2];
            if(num1 == num2){
                if (!result.size() || num1 != result.back()) {
                    result.push_back(num1);
                }
                p1++;
                p2++;
            }else if (num1 < num2) 
            {
                p1++;
            } else {
                p2++;
            }
        }

        return result;
    }
};

202-快乐数

题目链接:快乐数

思路: 题目中提到可能是无限循环 --> 要注意判断平方和是否出现过,若出现过则存在循环,即不是快乐数直接返回false。快速判断一个数是否存在 --> 哈希表

class Solution {
public:
    // 计算位数字的平方和
    int bitSquareSum(int n){
        int sum = 0;
        while(n){
            sum += (n % 10) * (n % 10);
            n /= 10;
        }
        return sum;
    }

    bool isHappy(int n) {
        // 哈希表
        unordered_set<int> set;
        while(1){
            int sum = bitSquareSum(n);
            if(sum == 1)
                return true;
            if(set.find(sum) != set.end())
                return false;
            set.insert(sum);
            n = sum;
        }
    }
};

1-两数之和

题目链接:两数之和

数据结构的选择:unordered_map

        - 在本题中既需要保存元素值,又需要保存下标 --> 选择map

        - 不要求键值有序 --> unordered_map

算法描述:遍历数组,存储当前值和坐标,并计算target - nums[i]是否存在,若存在则返回当前下标和查找到的元素的下标。

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

感觉哈希表的题在算法逻辑上都并没有很难理解,关键在于意识到应该选择哈希来处理并且要选择合适的数据结构。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值