哈希表篇(三)

哈希表篇(三)

一、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介绍

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Qxq3y2t-1651201019490)(https://s2.loli.net/2022/04/28/S7E84AI6triwsFm.png)]

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
  • 没找到,就将这个数以及对应的位置存进哈希表
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值