查找算法

查找3—散列表的查找

拜拜、爱过 提交于 2019-12-11 11:56:08
前言: 这是查找这个知识点的最后一个部分,个人感觉这部分真的很好理解,就简单的逻辑思维,不需要绕弯,基本上就可以解决大部分的题目。合理的应用查找的总体效率也是很高的 。主要说三个模块的事情: 构造方法 , 处理冲突方法 , 查找 。 那么引入一下,前面我们说了顺序表的查找、树表的查找,但是我们发现,就算再优化,它们的时间复杂度最小也是log 2 n级别的。那么我们肯定是希望能找到更优的算法,最好就是n(1)级别的,如果能利用公式直接的求解,那么不是直接就可以找到了,不需要依次比较了吗?所以就有了我们要说的散列表的查找(也叫哈希表)。 一、构造方法 来看看基本的概念: 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。 构造方法有很多, 数字分析法 、 平方取中法 、 折叠法 、 除留余数法 (这个是 最常用 的)。只需要思考一下就知道我们构造其实就是制定一个规则,使我们的元素可以按照这个规则查找到,当然

c++之STL总结

浪尽此生 提交于 2019-12-11 00:59:23
c++中的STL(Stand Template Library)提供了最基本的数据结构和算法,功能十分强大。主要分为 容器 (数组,队列,链表,栈,集合等等), 迭代器 (一种对象,用来遍历容器中的元素)和常见算法(排序,反转等) 文章目录 容器 字符串 vector list deque stack multiset&set multimap&map 容器 字符串 包含文件:c++头文件中: #include<string> 常用方法: 初始化: string str:生成空字符串 string s ( str ) :生成字符串为str的复制品 string s ( str , strbegin , strlen ) :将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值 string s ( cstr , char_len ) :以C_string类型cstr的前char_len个字符串作为字符串s的初值 string s ( num , c ) :生成num个c字符的字符串 string s ( str , stridx ) :将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值 直接用另一个字符串赋值 如str2 . assign ( str1 ) ; 即用str1给str2赋值 . 用另一个字符串的一个子串赋值 如str3

在排序数组中查找元素的第一个和最后一个位置

耗尽温柔 提交于 2019-12-11 00:39:12
给定一个按照升序排列的整数数组 nums,和一个目标值 target。 找出给定目标值在数组中的开始位置和结束位置。 你的算法时间复杂度必须是 O(log n) 级别。 如果数组中不存在目标值,返回 [-1, -1]。 示例 1: 输入 : nums = [ 5 , 7 , 7 , 8 , 8 , 10 ] , target = 8 输出 : [ 3 , 4 ] 示例 2: 输入 : nums = [ 5 , 7 , 7 , 8 , 8 , 10 ] , target = 6 输出 : [ - 1 , - 1 ] 题目分析; 根据题目中的升序数组,且要查找目标值,则想到用二分查找。 如果数组中存在目标值的话,就返回它的开始出现位置和结束出现位置,没有的话就返回-1; 采用二分查找分别查找target出现的最左边位置和最右边位置; 需要注意到的一个优化地方是:在查找最左边位置的时候查找的范围是0——nums.length - 1,但是在查找最右边位置的时候查找的范围是result[0]——nums.length - 1,因为如果查找到target在最左边出现的位置了,那么查找最右边出现的位置时就不需要从0开始查找,而是从result[0]即从最左边出现的位置开始查找。 代码实现: public int [ ] searchRange ( int [ ] nums , int

控制反转(IoC)与依赖注入(DI)

心不动则不痛 提交于 2019-12-10 04:19:12
原文: http://zhangjunhd.blog.51cto.com/113473/126530 1. 控制反转 (Inversion of Control) 与依赖注入 (Dependency Injection) 控制反转即IoC (Inversion of Control),它把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转移,从程序代码本身转移到了外部容器。 IoC是一个很大的概念,可以用不同的方式来实现。其主要实现方式有两种:<1>依赖查找(Dependency Lookup): 容器 提供回调接口和上下文环境给 组件 。EJB和Apache Avalon都使用这种方式。<2>依赖注入(Dependency Injection):组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。后者是时下最流行的IoC类型,其又有接口注入(Interface Injection),设值注入(Setter Injection)和构造子注入(Constructor Injection)三种方式。 图1 控制反转概念结构 依赖注入之所以更流行是因为它是一种更可取的方式:让容器全权负责依赖查询,受管组件只需要暴露JavaBean的setter方法或者带参数的构造子或者接口

数据结构与算法(十)---跳表的实现

余生长醉 提交于 2019-12-09 22:40:46
一、概述 什么是跳表 跳表怎么实现 二、跳表 1. 跳表的定义和实现意义 我们知道二分查找法的前提是有序数组,那么有没有类似的让链表也证婚词类似"二分"查找的算法,那就是 跳表 了:它支持快速的插入、删除、查找操作,实现方式没有红黑树那么复杂,甚至可以代替它。Redis的有序集合就是使用跳表实现的, 链表的随机访问数据的时间复杂度是O(n),我们在链表的基础上,每两个结点提取一个结点到上一级,我们把抽出来的那一级叫作 索引 或 索引层 。图中的 down 表示 down 指针,指向下一级结点。 假如我们要差早16这个元素,我们通过第一级索引进行遍历,当到达13是,发现下一索引元素的值为17,那么16就应该在13和17之间,然后从索引层的13利用down指针,查找到原始链表的13,开始往后遍历得到需要查找的元素,原来需要对遍历10个,现在只需要6个节点;效率提高了;**如果在第一级索引上,在提取一层索引,会怎样呢? 这里直接查找1-64个元素,体验下效率: 查找效率从62次到了11次,这就是跳表。 2. 跳表的时间复杂度 普通链表的时间复杂度是O(N),怎么计算跳表的时间复杂度呢? 每两个结点会抽出一个结点作为上一级索引的结点,那第一级索引的结点个数大约就是 n/2,第二级索引的结点个数大约就是 n/4,第三级索引的结点个数大约就是 n/8,依次类推,也就是说,第 k

散列表与hash函数

纵饮孤独 提交于 2019-12-09 22:25:40
散列表: hash冲突解决 1)开放定址法 : 存入:冲突的 进行二次处理,加线性,平方等;以线性为例,会逐个向下找,直到找到一个空的位置然后放进去 查找:与存入相似,先hash定位起始的查找位置,然后向下找等于的对象,如果遇到空的说明不存在 删除:因为上面查找遇空则说明不存在,所以不可以直接删除,仅仅可以标记删除 2)链表: 3)再hash:产生冲突时,计算另一个哈希函数地址,到不冲突为止。使用一组散列函数 hash1(key),hash2(key),hash3(key)……我们先用第一个散列函数,如果计算得到的存储位置已经被占用,再用第二个散列函数,依次类推,直到找到空闲的存储位置。 4)公共溢出区:把溢出的放到一起 装载因子=填入表中的元素个数/散列表的长度 假设我们有 10万条URL 访问日志次数表,如何按照访问次数给 URL 排序? 1:保存次数 遍历 10 万条数据,以 URL 为 key,访问次数为 value,存入散列表,同时记录下访问次数的最大值 K,时间复杂度 O(N)。 k不大可以使用桶排序,否则快排 有两个字符串数组,每个数组大约有 10 万条字符串,如何快速找出两个数组中相同的字符串? 一个用来查,一个用来插入 以第一个字符串数组构建散列表,key 为字符串,value 为出现次数。再遍历第二个字符串数组,以字符串为 key 在散列表中查找,如果

基本查找算法

…衆ロ難τιáo~ 提交于 2019-12-09 20:13:29
顺序查找: 时间复杂度 O(n); 步骤描述: 循环 n 次,将每一个值与要查找的值作比较 代码实现: Public int search(int[] array,int num){ For(int i=0;i<num;i++){ If(array[i]==num){ return i+1; } } Return -1; } 二分查找 : 时间复杂度: O(log2n) 步骤描述: 咋限定条件下,递归的找到数组最中间的值 middle ,比较和要查找的值的大小。根据大小递归调用,如果相等则查找成功; 代码实现: Int array[]; Int num; Public int Search(int[] array,int begin,int end){ If(num>array[end]||num<array[begin]||begin>end){ Return -1; } Int middle=(begin+end)/2; If(num>array[middle]){ Search(array,middle+1,end); Return; }else if(num<array[middle]){ Search(array,begin,middle-1); Return; } Return middle; } 插值查找: 在二分查找的基础上,每次查找条件不是从中间平分

数据结构与算法——常用数据结构及其Java实现

懵懂的女人 提交于 2019-12-09 18:27:30
本文采用Java语言来进行描述,帮大家好好梳理一下,在工作和面试中用的上数据结构与算法。亦即总结常见的的数据结构,以及在Java中相应的实现方法,务求理论与实践一步总结到位。 常用数据结构 数组 数组是相同数据类型的元素按一定顺序排列的集合,是一块连续的内存空间。数组的优点是:get和set操作时间上都是O(1)的;缺点是:add和remove操作时间上都是O(N)的。 Java中,Array就是数组,此外,ArrayList使用了数组Array作为其实现基础,它和一般的Array相比,最大的好处是,我们在添加元素时不必考虑越界,元素超出数组容量时,它会自动扩张保证容量。 Vector和ArrayList相比,主要差别就在于多了一个线程安全性,但是效率比较低下。如今java.util.concurrent包提供了许多线程安全的集合类(比如 LinkedBlockingQueue),所以不必再使用Vector了。 链表 链表是一种非连续、非顺序的结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的,链表由一系列结点组成。链表的优点是:add和remove操作时间上都是O(1)的;缺点是:get和set操作时间上都是O(N)的,而且需要额外的空间存储指向其他数据地址的项。 查找操作对于未排序的数组和链表时间上都是O(N)。 Java中,LinkedList 使用链表作为其基础实现。

经典算法系列之:二分查找

蓝咒 提交于 2019-12-09 13:44:21
1、前言 算法,在计算机中的地位,就相当于人类大脑的决策中枢系统,哪怕最简单的算法,其精妙的思维方式,都可以让人开启一扇新的视窗。 算法,它不仅仅只是狭义的用来解决计算机科学领域的问题,更是一种“思维方式”。算法思维,是一种深度思考和创造的过程。 算法,只有真正理解了,而不只是所谓的知道,并将应用到生活、工作、学习等各个方面,它将一定使人受益终生。 2、原理推导 二分查找 ,前提是在排好序的基础上,每次查找,将数据集合分成两个部分,取中间索引数值与被查找的数值比较,逐次缩小查找范围,直到找到数值。 给定一组 {1,2,3,4,5,6} 的原始有序数组,按照从小到大升序排列。 #step1 初始化低位索引为0,高位索引为数组长度减1索引为5,低位+高位除2,中间索引取整为:2=(0+5)/2,对应的数值就是数组中的3。 #step2 第一次比较,数值【5】大于【3】,所以低位索引被修为3=2+1,对应数组中的数值【4】,高位索引不变还是5,低位+高位除2,中间索引取整为:4=(3+5)/2,对应的数值就是数组中的【5】。 至此,二分查找已经完成,数值【5】在数组中的索引位置为: 4 ,在本次查找过程中,我们只用到两次查找就找到了被查找的数值,大大提高了查询效率。 3、代码示例 # 排序是前提,假设已经是有序数组 public int dichotomy(int array[],int

大数据

我只是一个虾纸丫 提交于 2019-12-08 19:03:17
  第一部分、十道海量数据处理面试题   1、海量日志数据,提取出某日访问百度次数最多的那个IP。   此题,在我之前的一篇文章 算法里头有所提到,当时给出的方案是:IP的数目还是有限的,最多2^32个,所以可以考虑使用hash将ip直接存入内存,然后进行统计。   再详细介绍下此方案:首先是这一天,并且是访问百度的日志中的IP取出来,逐个写入到一个大文件中。注意到IP是32位的,最多有个2^32个IP。同样可以采用映射的方法,比如模1000,把整个大文件映射为1000个小文件,再找出每个小文中出现频率最大的IP(可以采用hash_map进行频率统计,然后再找出频率最大的几个)及相应的频率。然后再在这1000个最大的IP中,找出那个频率最大的IP,即为所求。   2、搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。   假设目前有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门。),请你统计最热门的10个查询串,要求使用的内存不能超过1G。   典型的Top K算法,还是在这篇文章里头有所阐述。 文中,给出的最终算法是:第一步、先对这批海量数据预处理,在O(N)的时间内用Hash表完成排序;然后,第二步、借助堆这个数据结构