c++数据结构与算法学习记录-哈希表(力扣202题快乐数)

一.哈希表

概念

哈希表是一个利用哈希函数来储存数据,储存位置的数据结构,通常支持一下操作:

  • insert(key,value): 插入键值对(key,value)
  • get(key): 如果存在键入的key值对则返回其值value,否则返回空值
  • delete(key): 删除键为key的键值对
    哈希表(Hash Table,又称散列表),是一种线性表的存储结构。哈希表由一个直接寻址表和一个哈希函数构组成。哈希函数h(k)将元素关键字k作为自变量,返回元素存储的下标。如图所示
    在这里插入图片描述

哈希冲突

哈希冲突:由于哈希表的大小是有限的,而要存储的总量是无限的,因此对于任何哈希函数,都会出现两个不同元素映射到同一个位置上的情况,这种情况叫做哈希冲突。比如h(k)=k%7,h(0)=h(7)=h(14)

解决哈希冲突方法:

1.开放寻址法:如果哈希函数返回位置已经有值,则可以向探查新的位置来存储这个值。

线性探索:如果位置i被占用,则探查i+1,i+2,……

二次探索:如果位置i被占用,则探查 i + 1 2 , i − 1 2 , i + 2 2 , i − 2 2 … … i+1^2,i-1^2,i+2^2,i-2^2…… i+12,i12,i+22,i22……,

二度哈希:有n个哈希函数,当使用第一个哈希函数h1发生冲突时。则尝试下一个函数。
2.拉链法
在这里插入图片描述

哈希函数

除法哈希法:h(k)=k%m

乘法哈希法: h ( k ) = f l o o r ( m ∗ ( A ∗ k e y ) ) h(k)=floor(m*(A*key)) h(k)=floor(m(Akey))

全域哈希法: h a , b ( k ) = ( ( a ∗ k e y + b ) m o d p ) m o d m h_{a,b}(k)=((a*key+b)mod\enspace p)mod\enspace m ha,b(k)=((akey+b)modp)modm

a,b=1,2,3……p-1, mod=%

二.哈希结构-集合

c++标准库提供了三种集合的数据结构,分别如下

集合底层实现是否有序数值是否可以重复能否更改数值查询效率增删效率
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。

三.题目描述

「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。

如果 n 是快乐数就返回 True ;不是,则返回 False 。

示例:

输入:19
输出:true
解释:
1^2 + 9^2 = 82
8^2 + 2^2 = 68
6^2 + 8^2 = 100
1^2 + 0^2 + 0^2 = 1

四.思路

可以设置循环来不断更新输入值,当输入值变为1则循环结束,输出true。当循环过程中两次出现同一个值,说明进入了死循环,判断同一个值是否出现两次可以借助unordered_set储存每次的输入值,当输入值可以在集合中找到时则视为其出现两次.

五.代码

class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> set;//定义集合保存每次的求和值
        while(1){
            int sum=0;
            
            while(n)//求每位的平方和
            {
                int spe=n%10;
                n/=10;
                sum+=(spe*spe);
            }
            if(sum==1)//快乐数
                return true;
            if (set.find(sum) != set.end())//在集合中出现过,陷入循环
                return false;
            else
                set.insert(sum);//  添加到集合中
             n=sum;
        }
    }
};

set.end()返回指向容器中最后一个元素之后位置的迭代器,set.find(key)表示查找值为key的元素,如果找到,则返回一个指向该元素的正向迭代器;如果没找到,则返回一个与end()方法相同的迭代器。set.find(sum) != set.end()则表示查询值在集合中。

  • 24
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值