IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码随想录算法训练营第六天| 哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和 -> 正文阅读

[数据结构与算法]代码随想录算法训练营第六天| 哈希表理论基础 242.有效的字母异位词 349. 两个数组的交集 202. 快乐数 1. 两数之和

哈希表理论基础

?
哈希表是什么:能通过关键码的值直接访问元素的数据结构
哈希函数:把要查询的元素列表,映射为哈希表上的索引。比如除留余数法(H(key)=key MOD p (p<=m))取关键字被某个不大于哈希表表长m的数p除后所得余数为哈希地址。
哈希碰撞:多个关键字映射到同一个索引下标的位置。 解决哈希碰撞: 1.拉链法? 发生冲突的元素都被储存在链表中,可以通过索引去找到他们. 2.使用线性探测法,一定要保证tableSize大于dataSize。需要依靠哈希表中的空位来解决碰撞问题,在冲突的位置向下找一个空位去放冲突的元素。
内部实现原理:
我们想使用哈希法来解决问题的时候,我们一般会选择: 数组,集合,映射,主要来看一下集合和映射
在C++中,set 和 map 分别提供以下三种数据结构,其底层实现以及优劣如下表所示:

std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加。

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

那么再来看一下map ,在map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。?

?std::unordered_map 底层实现为哈希表,std::map 和std::multimap 的底层实现是红黑树。同理,std::map 和std::multimap 的key也是有序的

总结:unordered_set 和 unordered_map的底层实现都是哈希表,set, multiset, map, multimap, 底层实现都是红黑树。set 的话不能修改,只能增删。 map的话,key都是不能修改的,value可以去修改。使用红黑树实现的结构,都是有序的,并且查找和增删复杂度都是O(logn), 使用哈希表实现的unordered_set/map都是无序的,查询和增删效率都是O(1).

什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候 或者?需要判断一个元素是否出现过就要考虑哈希法。 这句话很重要,大家在做哈希表题目都要思考这句话。

242.有效的字母异位词

先提供最容易想到的解法,去判断两个dict是否不同:

def isAnagram(self, s: str, t: str) -> bool:
        dicta = {}
        dictb = {}
        for i in s:
            dicta[i] = dicta.get(i,0) + 1
        for i in t:
            dictb[i] = dictb.get(i,0) + 1
        return dicta == dictb

然后是用数组去记录出现的次数,ord(i) - ord('a'), 总共有26个,正好映射到长度为26的数组的索引

def isAnagram(self, s: str, t: str) -> bool:
        record = [0] * 26
        for i in s:
            record[ord(i)-ord('a')] += 1
        for i in t:
            record[ord(i)-ord('a')] -= 1
        for i in range(26):
            if record[i] != 0:
                return False
        return True

349.两个数组的交集

遍历, 拿集合去重? ? or? ? 直接求交集然后转化成list出

def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        a, res = set(), list()
        for i in nums1:
            if i in nums2:
                a.add(i)
        for i in a:
            res.append(i)
        return res
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
        return list(set(nums1) & set(nums2))

202. 快乐数

题目中说了会?无限循环,那么也就是说求和的过程中,sum会重复出现,这对解题很重要!当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法了。

所以这道题目使用哈希法,来判断这个sum是否重复出现,如果重复了就是return false, 否则一直找到sum为1为止。

判断sum是否重复出现就可以使用unordered_set。

还有一个难点就是求和的过程,如果对取数值各个位上的单数操作不熟悉的话,做这道题也会比较艰难。

    def isHappy(self, n: int) -> bool:
        def cal(num: int) -> int:
            sum_ = 0
            while num:
                sum_ += (num % 10) ** 2
                num = num // 10
            return sum_

        record = set()
        while True:
            sum = cal(n)
            if sum == 1:
                return True
            if sum in record:
                return False
            else:
                record.add(sum)
            n = sum

1. 两数之和

在这个题中,我们找两个数之和是否存在,当我们遍历到一个数的时候,我们想知道,target - nums[i], 是否之前遍历到过。这样的话,我们才需要用一个东西去储存之前遍历到的元素的值。

那么为什么要用map, 因为我们需要返回下标,元素值,下标,谁做key, 谁做value呢?我们需要返回的东西,要做value.

那么就是 我们在遍历的时候,要把遍历到的元素的值nums[i], 当做key, 把下标i当做value, 去做一个储存。那么我们在查找的时候,就能很容易的以O(1)的复杂度去查找到是否有 target - nums[i]的存在,并且返回下标

def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = {}
        for i in range(len(nums)):
            if target - nums[i] in hashtable:
                return [i,hashtable[target - nums[i]]]
            hashtable[nums[i]] = i

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-09-30 01:12:58  更:2022-09-30 01:14:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 16:34:27-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码