2022年10月17日算法题学习打卡

80 阅读2分钟

day6 哈希表

哈希基础知识

  • 数组
  • set
  • map

242.有效的字母异位词

题目链接/文章讲解/视频讲解: programmercarl.com/0242.%E6%9C…

**个人思路:**本题较为基础,由于小写字母只有26个,因此可以考虑开一个26的数组记录下字符串中每个字符出现的次数,再通过比较字符串中每个字符的次数是否相等。

代码:

class Solution {
public:
    bool isAnagram(string s, string t) {
        int nums[26] = {0};
        int numt[26] = {0};
        for(int i=0;i<s.size();i++)
        {
            nums[s[i] - 'a']++;
            //printf("%d ", nums[s[i] - 'a']);
        }
        //printf("\n");
        for(int i=0;i<t.size();i++)
        {
            numt[t[i] - 'a']++;
        }
        for(int i =0;i<26;i++)
        {
            if(nums[i] !=numt[i]) return false;
        }
        return true;
    }
};

349. 两个数组的交集

题目链接/文章讲解/视频讲解:programmercarl.com/0349.%E4%B8…

个人思路: 本题思路比较简单,主要是对一个比较新的数据结构(哈希表)进行了运用,同时对于set,multiset,unordered_set需要进行选择,如果不需要对数据进行排序,并且数据不需要重复,可以选择unordered_set。

下图来源于代码随想录

image.png

set的一些常用操作:

  • begin()返回指向第一个元素的迭代器
  • clear()清除所有元素
  • count()返回某个值元素的个数
  • empty()如果集合为空,返回为真
  • end()返回指向最后一个元素之后的迭代器,不是最后一个元素
  • erase()删除集合中的元素
  • find()返回一个指向被查找到元素的迭代器
  • insert()在集合中插入元素
  • max_size() 返回集合中能容纳的元素的最大限值
  • size()集合中元素的数目
  • swap()交换两个集合变量

代码:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> result_set; 
        unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for(int num:nums2)
        {
            if(nums_set.find(num)!=nums_set.end())
            {
                result_set.insert(num);
            }
        }
        return  vector<int>(result_set.begin(),result_set.end());
    }
};

202. 快乐数

建议:这道题目也是set的应用,其实和上一题差不多,就是 套在快乐数一个壳子

题目链接/文章讲解:programmercarl.com/0202.%E5%BF…

个人思路:

本题与上述题有点类似,主要是模拟快乐数的判断的方式一步步写代码,如果一个数不是快乐数那么该数就一定会无限循环,因此需要记录下原先出现过的结果对数字进行判断(是否进入了无限循环),很自然的想到了用哈希表来存储出现过的数字,以便更好的判断。

代码:

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> nums;
        while(1){
            int sum = 0;
            while(n){
                int tmp = n%10;
                n/=10;
                sum += tmp*tmp;
            }
            if(nums.find(sum)!=nums.end()) break;
            else if(sum == 1) return true;
            nums.insert(sum);
            n=sum;
        }
        return false;
    }
};

1. 两数之和

题目链接/文章讲解/视频讲解:programmercarl.com/0001.%E4%B8…

个人思路:

本题如果采用暴力的解法,时间复杂度为o(n^2),主要每次比较都需要遍历整个数组,因此很自然的想到采用哈希表,使得每次查找的复杂度降为1,与上述不同的是这里需要返回数组下标,因此可以采用map,<key,value>,第一维已遍历的数,第二维对应于该数所对应的数组下标。

下图来源于代码随想录

image.png

代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> dec;   //差值,坐标  相对于set多了一维
        for(int i=0;i<nums.size();i++)
        {
            auto iter = dec.find(target - nums[i]);
            if( iter!=dec.end()) return {iter->second, i};
            dec.insert(pair<int,int>(nums[i],i));
        }
        return {};
    }
};