代码随想录-哈希表

基础知识

哈希表是一种根据关键码的值直接访问数据的数据结构。一般用来快速判断一个元素是否出现在集合中。

哈希函数

hashCode通过特定编码格式,可以将其他数据格式转化为不同的数值。然后哈希函数把这些值映射在哈希表的索引上。

哈希碰撞

遇到哈希碰撞后,有两种解决方法:

拉链法:将冲突的值依次存储在链表中。

线性探测法:将冲突的值存储在下一个空位,因此必须保证 tableSize 大于 dataSize 。

三种哈希结构

分别是:数组、集合(set)、映射(map)

当我们使用集合解决哈希问题的时候,优先使用 unordered_set ,因为它的查询和增删效率最优;

若要求集合有序,就使用 set

若要求集合不仅有序,还要有重复数据,就使用 multiset

前者的底层实现用哈希表,后两者用红黑树

有效的字母异位词

在这里插入图片描述

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

两个数组的交集

在这里插入图片描述

unordered_set

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) {
    
    
            // find()查找该元素第一次出现的位置,end()指向末尾元素的下一个位置
            if (nums_set.find(num) != nums_set.end()) {
    
     // 说明找到了
                result_set.insert(num); // 放入交集
            }
        }
        return vector<int>(result_set.begin(), result_set.end()); // 这里用vector
    }
};

两数之和

在这里插入图片描述

暴力法

class Solution {
    
    
public:
    vector<int> twoSum(vector<int>& nums, int target) {
    
    
        for (int i = 0; i < nums.size(); i++) {
    
    
            for (int j = i + 1; j < nums.size(); j++) {
    
    
                if (nums[i] + nums[j] == target) {
    
    
                    return {
    
    i, j};
                }
            }
        }
        return {
    
    };
    }
};

时间复杂度:O(n^2)

Map

在本题中,用数组不好,因为元素很少;也不适用 set ,因为 set 只保存一个 key ,但我们既要比较值,同时保存下标。

故选用 map ,<key, value> 用 key 表示值,用 value 记录下标。

class Solution {
    
    
public:
   vector<int> twoSum(vector<int>& nums, int target) {
    
    
       unordered_map<int, int> map;
       for (int i = 0; i < nums.size(); i++) {
    
    
           auto iter = map.find(target - nums[i]); // auto 自己推演数据类型
           if (iter != map.end()) {
    
      // 找到一个
           	return {
    
    i, iter->second}; // first表示key,second表示value
           }
           map.insert(pair<int, int>(nums[i], i)); // map<X,Y>实际存储的是pair<const X,Y>
       }
       return {
    
    };
   }
};

时间复杂度:O(n)

四数相加

在这里插入图片描述

原式可转化为 nums1[i] + nums2[j] = -nums3[k] - nums4[l]

class Solution {
    
    
public:
    int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
    
    
		unordered_map <int, int> umap;
        for (int a : nums1) {
    
    
            for (int b : nums2) {
    
    
                umap[a + b]++;
            }
        }
        // 找0 - (c + d)
        int count = 0;
        for (int c : nums3) {
    
    
            for (int d : nums4) {
    
    
                if (umap.find(0 - (c + d)) != umap.end()) {
    
    
                    count += umap[0 - (c + d)];
                }
            }
        }
        return count;
    }
};

三数之和

在这里插入图片描述

哈希解法

输出结果与预期结果不符,不能吧。挨个对了一遍,没错啊

class Solution {
    
    
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
    
    
		vector<vector<int>> result;
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i++) {
    
    
            if (nums[i] > 0) break;
            if (i > 0 && nums[i - 1] == nums[i]) {
    
     // 元素a去重
                continue;
            }
            unordered_set<int> set;
            for (int j = i + 1; j < nums.size(); j++) {
    
    
                if (j > i + 2 && nums[j - 2] == nums[j - 1] && nums[j - 1] == nums[j]) {
    
     // 元素b去重
                    continue;
                }
                int c = 0 - (nums[i] + nums[j]);
                if (set.find(c) != set.end()) {
    
    
                    result.push_back({
    
    nums[i], nums[j], c});
                    set.erase(c); // 元素c去重
                } else {
    
    
                    set.insert(nums[j]) // 不懂
                }
            }
        }
        return result;
    }
};

双指针法

学不懂了,先放着

四数之和

猜你喜欢

转载自blog.csdn.net/qq_50209297/article/details/130941509