六月集训(第07天)—哈希表

哈希表

1. 442. 数组中重复的数据

    思路1:
        首先是开空间为$O(n)$的数组空间,建立hash映射。
        

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        bool hash[100001];
        memset(hash, 0, sizeof(hash));
        vector<int> ans;
        int nums_size = nums.size(), i;
        for (i = 0; i < nums_size; ++i) {
            if (!hash[nums[i]]) hash[nums[i]] = 1;
            else ans.push_back(nums[i]);
        }
        return ans;
    }
};

    思路2:
        将空间优化为$O(1)$
        利用nums[]本身作为hash表,nums[i]出现一次,将其作为下标对应的值取反(标记出现了)idx = abs(nums[i]),如果nums[idx]是负的,则idx出现两次,将idx加入答案。

class Solution {
public:
    vector<int> findDuplicates(vector<int>& nums) {
        vector<int> ans;
        int nums_size = nums.size(), i;
        nums.push_back(1);
        for (i = 0; i < nums_size; ++i) {
            int idx = abs(nums[i]);
            if (nums[idx] > 0) nums[idx] = -nums[idx];
            else ans.push_back(idx);
        }
        return ans;
    }
};

2. 2068. 检查两个字符串是否几乎相等

    思路:
        利用hash记录每个字母出现的次数,对于word1,每出现一次,记录+1;word2中字母每出现一次,hash-1,最后如果有某个字母的出现次数的绝对值大于3,则不满足;否则满足。

class Solution {
public:
    bool checkAlmostEquivalent(string word1, string word2) {
        int hash[26];
        memset(hash, 0, sizeof(hash));
        int word1_len = word1.length();
        int word2_len = word2.length();
        int i;
        for (i = 0; i < word1_len; ++i) {
            hash[word1[i] - 'a']++;
        }
        for (i = 0; i < word2_len; ++i) {
            hash[word2[i] - 'a']--;
        }
        for (i = 0; i < 26; ++i) {
            if (hash[i] > 3 || hash[i] < -3) return false;
        }
        return true;
    }
};

3. 2283. 判断一个数的数字计数是否等于数位的值

    思路:
        记录每个值出现的次数,与对应的数字应该出现的次数进行比对,不满足则返回false,否则返回true。

class Solution {
public:
    bool digitCount(string num) {
        int hash[11];
        memset(hash, 0, sizeof(hash));
        int num_len = num.length(), i;
        for (i = 0; i < num_len; ++i) {
            hash[ num[i] - '0' ]++;
            if (hash[i] > num[i] - '0') return false;   /* 优化一下,如果某个数字出现的次数已经超出了对应的限制,则不满足 */
        }
        for (i = 0; i < num_len; ++i) {
            if (hash[i] != num[i] - '0') return false;
        }
        return true;
    }
};

4. 884. 两句话中的不常见单词

        先尝试自己写,遇到两个难点:
            1. hash映射函数:想了半天没想到合适的hash映射关系,最后想到利用每个字母在单词的第几位,就乘上几作为加权。
            2. 如何统计两个字符串中只出现一次,而在另一个中没有出现,代码越写越像shi山。最后一看英雄哥将两个字符串拼起来,统计只出现一次的单词,直呼妙不可言。
        C++的map函数太香了,学一手迭代器的使用。此时此刻我只想说STL NB!
    思路:
        将两字符串拼接,建立hash映射,记录每个单词出现的次数,将只出现一次的单词作为答案。


class Solution {
public:
    vector<string> uncommonFromSentences(string s1, string s2) {
        unordered_map<string, int> hash;
        string temp = "";
        vector<string> ans;

        // 将两字符串拼接
        s1 += " ";
        s1 += s2;
        s1 += " ";

        // 利用哈希表,记录每个单词出现的次数
        int s_len = s1.length(), i;
        for (i = 0; i < s_len; ++i) {
            if (s1[i] == ' ') {
                hash[temp]++;
                temp = "";
            } else {
                temp += s1[i];
            }
        }

        // 取出只出现一次的单词作为答案
        for (auto iter = hash.begin(); iter != hash.end(); ++iter) {
            if (iter->second == 1) ans.push_back(iter->first);
        }

        return ans;
    }
};
posted @ 2022-06-07 14:47  番茄元  阅读(45)  评论(0)    收藏  举报