代码随想录第6天 | ●哈希表理论基础●242.有效的字母异位词●349. 两个数组的交集●202. 快乐数●1. 两数之和

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

思路:

1.ASCII和哈希函数,存入数组,比较数组相等否
2.首先选择数据结构,题目只有小写字母,ASCII连续,选用数组,一个字符串遍历,在哈希数组中存入字母出现频率,第二个字符串遍历,做减法。(不需要记ASCII,直接减字母,编译器自己算)
时间复杂度: O(n)
空间复杂度: O(1)

坑:

补充:

哈希表理论基础

  1. 哈希表是hash table 又叫散列表, 多用于快速判断某意思元素是否在集合里。(数组是一个哈希表。)
  2. 哈希函数hash function把 实际的目标 映射到 哈希表上。
  3. 哈希碰撞(冲突) 实际目标映射到了相同索引下标的位置。解决方法:
    ①拉链法:冲突的元素 存储在链表中
    ②线性探测法:要保证tableSize 大于dataSize,冲突的元素 存储在冲突位置往后的空位上。
    常见的哈希结构
  4. 数组
  5. set(集合)
  6. map(映射)
    set和map的底层实现及优劣表
集合set 底层实现 是否有序 数值是否可以重复 能否更改数值 查询效率 增删效率
std::set 红黑树 有序 O(log n) O(log n)
std::multiset 红黑树 有序 O(logn) O(logn)
std::unordered_set 哈希表 无序 O(1) O(1)

使用集合来解决哈希问题的时候,优先使用unordered_set,因为它的查询和增删效率是最优的,
如果需要集合是有序的,那么就用set,
如果要求不仅有序还要有重复数据的话,那么就用multiset。

映射map 底层实现 是否有序 数值是否可以重复 能否更改数值 查询效率 增删效率
std::map 红黑树 key有序 key不可重复 key不可修改 O(logn) O(logn)
std::multimap 红黑树 key有序 key可重复 key不可修改 O(log n) O(log n)
std::unordered_map 哈希表 key无序 key不可重复 key不可修改 O(1) O(1)

红黑树
红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

题目:349.两个数组的交集

思路:

  1. 类似上题,使用数组,根据元素的数值,存入数组对应下标中 但如果数值很大,映射到数组下标就不合适。
  2. 该题去重,则选择unordered_set
    时间复杂度: O(n + m) m 是最后要把 set转成vector
    空间复杂度: O(n)

坑:

class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        if(nums1.size()<nums2.size()){
            nums1.swap(nums2);
        }
        unordered_set<int> hash_set(nums1.begin(),nums1.end());
        unordered_set<int> result_set;
       for(int num: nums2){
            if(hash_set.find(num)!=hash_set.end()){
                result_set.insert(num);
                 //在集合hash_set中使用find函数查找num,找到返回一个指向该元素的正向迭代器,反之,返回一个类似end()的迭代器
                 //找到则将该元素存入结果集合result_set中
            }
       }
        return vector<int>(result_set.begin(),result_set.end());
        //因为函数返回类型是vector 所以转换一下类型
    }
};

补充:

set集合
C++ STL unordered_set容器

成员方法 功能
find(key) 查找以值为 key 的元素,如果找到,则返回一个指向该元素的正向迭代器;反之,则返回一个指向容器中最后一个元素之后位置的迭代器(一个与end() 方法相同的迭代器)。
count(key) 在容器中查找值为 key 的元素的个数。
empty() 若容器为空,则返回 true;否则 false。
size() 返回当前容器中存有元素的个数。

范围for循环

范围循环:
for (类型 element : myVector) {
    std::cout << element << " ";
}

题目:202.快乐数

思路:

对n取余存入unordered_set 然后判断和是否为1,题目说可能无限循环,不知怎么判断

  1. 无限循环是sum会重复出现 ,所以将每次循环的sum存入sums_set, 查找是否存在。
    2.看leetcode题解:双指针

坑:

1.数位分离,求平方和,可以简单的while和sum,不用多一步将个个数位上的值存入nums_set
2. % 是整数取余,/ 是除号

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> sums_set;
        int sum = 0;
        while (sum != 1) {
            sum=0;  //错误,sum 没有更新为0;
            while (n ) {// 错误 while的循环判断条件 不是n/10,这样会少判断元素
                sum+=(n%10)*(n%10);
                n = n / 10;
            }
            if(sums_set.find(sum)!=sums_set.end()){
                return false;
            }else{
                sums_set.insert(sum);
            }
            n=sum;
        }
        return true;
    }
};

题目:1.两数之和

思路:

  1. 暴力法,枚举数组中的每一个数 x,寻找数组中是否存在 target - x。遍历,与目标值作差,在数组中寻找差值
  2. 升级,方法一时间复杂度较高在于,target-1的遍历, 所以将遍历过的值x和下标保存到一个集合,之后遍历的时候来询问这个集合 ,target-x是否遍历过。因为需要保存值和下标 所以选用map,因为无序,-->unordered_map
    时间复杂度: O(n)
    空间复杂度: O(n)

坑:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> nums_map;
        vector<int> result;
        for(int i=0;i<nums.size();i++){
            if(nums_map.find(target-nums[i])!=nums_map.end()){
                result.push_back(i);
                result.push_back(nums_map.at(target-nums[i]));
                return result;
                //优化 使用迭代器
            }else{
                nums_map.insert({nums[i],i});
                //map以键值对的pair的方式插入{}
            }
        }
        return result;
    }
};
/*
使用迭代器
// 遍历当前元素,并在map中寻找是否有匹配的key
    auto iter = map.find(target - nums[i]); 
    if(iter != map.end()) {
        return {iter->second, i};
    }
    // 如果没找到匹配对,就把访问过的元素和下标加入到map中
    map.insert(pair<int, int>(nums[i], i));
    //没有返回return {};
*/

补充:

map相关
C++之STL整理(3)之map 用法(创建、赋值、方法)整理
STL 中的map是一个关联容器,它存储的元素都是键值对(key-value pair),并且根据键(key)自动排序的容器。map不允许键重复,每个键在map中只能出现一次。
map容器的每一个元素都是一个pair结构(pair<t1,t2>)的数据。
map容器的迭代器first和second,分别对应key 和value。 通过map->first;获得对应的值
pair结构
pair 通常用于将两个值组合成一个单一的实体,以便可以作为一个整体进行传递或返回。
这两个元素分别被称为 first 和 second。
包含头文件:#include

迭代器

迭代器是一种检查容器内元素并遍历元素的数据类型,通常用于对C++中各种容器内元素的访问,但不同的容器有不同的迭代器,

C++ 迭代器(iterator)超详解
迭代器的通用功能

  1. 比较两个迭代器是否相等(==、!=)。
  2. 前置和后置递增运算(++)。
  3. 读取元素的解引用运算符(*)。只能读元素,也就是解引用只能出现在赋值运算符的右边。
  4. 箭头运算符(->),解引用迭代器,并提取对象的成员。

今日总结

需要复习map,和迭代器的用法

posted @   跳圈  阅读(5)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示