算法训练营Day6 第三章 哈希表part1

哈希表理论基础 :
        首先,我们应当明确,什么时候使用哈希表来解题呢?答案就是: 当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。哈希表包括数组(vector)、set、map等多种数据结构,我们需要根据题目的要求判断选择哪一种数据结构最为合适。要注意set、multiset以及unordered_set之间的区别和联系,同时也要了解map、multimap以及unordered_map的底层结构。
        要注意unordered_set和unordered_map的底层结构为哈希,其中的数据是无序的;而set、multiset、map、multimap这些数据结构的底层是红黑树,数据是有序的,multi修饰的数据结构中允许存在相同的元素,没有multi修饰的则不存在相同元素,这一点要注意。

第一题: 242.有效的字母异位词 

        这道题比较简单,利用数组来解决非常合适,我就直接给出代码了:

        

class Solution {
public:
    bool isAnagram(string s, string t) {
        if(s.size() != t.size())
            return false;
        vector<int> arr(26, 0);
        for(auto i : s) {
            arr[i - 'a']++;
        }
        for(auto i : t) {
            if(--arr[i - 'a'] < 0)
                return false;
        }
        return true;
    }
};

 第二题: 349. 两个数组的交集 

        这道题要求给出两个数组的交集元素,且要求输出结果中的每个元素是唯一的,可以使用数组或者set类型的数据结构来解决问题,分别给出相应的代码。

        ①数组法:因为数字在[0, 1000]中,所以可以先设计一个大小为1001的数组来存放nums1中哪些数字出现过,出现过的数字置为1,没有出现的数字初始化为0即可,然后遍历nums2数组,将相交的元素放入结果集中,并将该位置置为0。代码如下所示:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int> v1(1001, 0);
        vector<int> ans;
        for(auto i : nums1) {
            v1[i] = 1;
        }
        for(auto i : nums2) {
            if(v1[i] == 1) {
                ans.emplace_back(i);
                v1[i]--;
            }
        }
        return ans;
    }
};

        ②set法:同理我们也可以使用set类型的数据结构来解题,首先将nums1中的元素放到一个unordered_set中去,这一步直接对nums1去重完成,然后遍历nums2中的元素,如果在上述的set中存在,我们就放到一个新建的unordered_set中,这样也不用担心会重复,最后返回一个题目要求的vector(这个数组用第二步中的set来初始化)即可,代码如下所示:

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

 第三题: 202. 快乐数 

        题目中说了会如果不是快乐数,会无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!因此可以使用哈希表来解题,使用set即可。

给出如下代码:

class Solution {
public:
    int getSum(int n) {
        int tmp = n;
        int ret = 0;
        while(tmp) {
            int m = tmp % 10;
            tmp /= 10;
            ret += m * m;
        }
        return ret;
    }

    bool isHappy(int n) {
        unordered_set<int> val;
        int sum = n;
        while(val.find(sum) == val.end()) {
            val.insert(sum);
            sum = getSum(sum);
            if(sum == 1)
                return true;
        }
        return false;
    }
};

拓展:这道题其实也可以使用快慢指针的方法来解题,可以把这道题看成链表是否为环形链表的问题,这个方法我之后补充一下,暂时没写!

 第四题:1. 两数之和 

        这道题是典型的使用unordered_map的题目,我们创建一个unordered_map,令其first为数组元素,second为数组下标,然后遍历数组,找寻map中是否存在(target - nums[i]),找到了就返回此时的下标和对应迭代器的second组成的数组。

        代码如下所示:

        

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

Day6任务完结啦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值