哈希表篇(三)

本文已参与[新人创作礼]活动,一起开启掘金创作之路

哈希表篇(三)

一、202. 快乐数

思路分析

由题意本题有两个重要点:

  1. 如何对数的每一位求该位置上的平方和
  2. 如果最后不是1,则会无限循环,导致一定会有sum重复

对于问题1,则我们选择对取数值各个位上的单数操作,通过对取值数的模10操作,达到取每一位的数的平方和。

对于问题2,则与哈希表相关——当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法,因此判断sum是否出现重复,就用到了unordered_set(出现重复元素即返回false)

代码

class Solution {
public:
    int getsum(int n){
        int sum = 0;
        while(n){//当n为0时跳出循环
            sum += (n%10)*(n%10);
            n /= 10;//从取该数的个位开始至十位百位往上
        }
        return sum;
    }
    bool isHappy(int n) {
        unordered_set<int> set;
        while(1){//这是一个死循环,无限循环下去,除了return
            int sum = getsum(n);
            if(sum == 1){
                return true;
            }
            if(set.find(sum)!=set.end()){
                return false;
            }
            else{
                set.insert(sum);
            }
            n = sum;
        }
    }
};

二、1. 两数之和

思路解析

1、暴力解法

对于寻找两数之和的数组问题,最简单直接的就是两层for循环,在逐次找到目标值后进行跳出即可。

代码

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

2、哈希表的使用

由于本道题目要求是一维进行加法计算匹配,一维进行输出下标,所以则要使用map

使用数组和set来做哈希法的局限。

  • 数组的大小是受限制的,而且如果元素很少,而哈希值太大会造成内存空间的浪费。
  • set是一个集合,里面放的元素只能是一个key,而两数之和这道题目,不仅要判断y是否存在而且还要记录y的下标位置,因为要返回x 和 y的下标。所以set 也不能用。

map是一种key value的存储结构,可以用key保存数值,用value在保存数值所在的下标。

C++中是map介绍

image-20220428142540767

std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。

由图可知:std::map 和std::multimap 的key也是有序的 (这个问题也经常作为面试题,考察对语言容器底层的理解)

这道题目中并不需要key有序,选择std::unordered_map 效率更高!

img

代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
            std::unordered_map<int, int>map;
            for(int i = 0; i < nums.size(); i++){
                auto cur = map.find(target - nums[i]);
                if(cur != map.end()){
                    return {cur->second, i};
                }
                map.insert(pair<int, int>(nums[i], i));
            }
            return {};
    }
};
代码解释
  • map的常用函数

    at 返回索引处元素的引用 begin 返回指向容器头的迭代器 cbegin 返回指向容器头的迭代器-const bucket 返回key所对应的桶(bucket)的编号 bucket_count 返回容器中桶(bucket)的个数 bucket_size 返回对应桶(bucket)中的元素个数 cend 返回指向容器尾元素后一个位置的迭代器 - const clear 清空容器 count 返回key对应元素的个数,因为unordered_map不允许有重复key,所以返回0或1

    emplace move emplace_hint 过迭代器位置进行emplace, 因此可以从参数位置开始搜索,速度更快 empty 判断容器是否为空 end 返回指向容器尾的迭代器 equal_range erase 删除元素 find 查找 get_allocator hash_function insert 插入元素 key_eq load_factor 返回容器当前负载系数 max_bucket_count 返回容器所能包含的桶的最大数量 max_load_factor 容器最大负载系数

    max_size 返回容器可以容纳的最大元素数 operator= 重载运算符 = operator[] 重载运算符 [],通过索引可返回对应元素的引用 rehash 参数n大于当前桶数,rehash,否则容器无变化 reserve n大于bucket_count*max_load_factor,rehash,否则容器无变化 size 返回容器中元素个数 swap 当前容器与参数容器中元素交换

  • 直接返回{},提高速率
  • it!=map.end()即能找到,则return
  • 没找到,就将这个数以及对应的位置存进哈希表
posted @ 2022-04-29 10:37  Luciferpluto  阅读(0)  评论(0)    收藏  举报  来源