查找算法及哈希表
1 二分查找
1.1 重要概念
- 拟解决的问题:判断某个区间是否包含某个元素,无法确定区间中包含重复元素的具体位置;
- 使用条件:查找的区间必须符合单调性;
- 本质:采用分治思想,将某个单调区间一分为二,保证留下的一半区间包含解,舍弃的一半区间不包含解;
- 时间复杂度:O(log2n)�(���2�)
- 计算方式:二分查找每查找一次将原问题的规模n缩减到1/2,最糟糕的情况为n=1时,二分查找获得结果,此时二分查找的次数为$n/2^x=1,即,即x = log_2n$
1.2 应用场景
- 判断某个单调区间是否包含某个元素;
- 前面一堆1,后面一堆0,如1111100000,查询最后一个1出现的位置;(特殊情况1)
- 前面一堆0,后面一堆1,如0000011111,查询第一个1出现的位置;(特殊情况2)
1.3 代码演示
// 1 3 5 7 9 10
int binary_search(int *arr, int n ,int x) {int head = 0, tail = n - 1, mid;while (head <= tail) {mid = (head + tail) >> 1;if (arr[mid] == x) return mid;if (arr[mid] < x) head = mid + 1;else tail = mid - 1;}return -1;
}// 1111100000
int binary_search1(int *arr, int n) {int head = -1, tail = n - 1, mid; // 当查找区间的元素全0时,为避免二义性,定义head=-1,而不是head=0while (head < tail) {mid = (head + tail + 1) >> 1; // 上取整,否则会出现死循环if (arr[mid] == 1) head = mid; // mid 有可能是最后一个1出现的位置else tail = mid -1;}// head = tail = -1 时,代表未找到,否则返回对应元素的位置return head;
}// 00000111111
int binary_search2(int *arr, int n) {int head = 0, tail = n, mid; // 当查找区间的元素全0时,为避免二义性,定义tail=n,而不是tail=n-1while (head < tail) {mid = (head + tail) >> 1;if (arr[mid] == 1) tail = mid; // mid 有可能是第一个1出现的位置else head = mid + 1;}// head = tail = n 时,代表未找到,否则返回对应元素的位置return head == n ? -1 : head;
}
2 三分查找
2.1 拟解决的问题
二分查找解决的是在单调序列中查找目标值的问题,而三分查找则是确定函数在凹/凸区间上的极值点;
2.2 算法描述
在函数f(x)的某个区间[l, r]上取2个分界点,其中m1位于l的1/3处,m2位于l的2/3处,即:$m1 = l + (r - l) / 3$,$m2 = r - (r - l) / 3$,这两个点m1、m2把区间 [l, r] 分为3 个子区间。这里以凸函数(即有最大值)为例讨论:
- 若f(m1) < f(m2),说明极值点位于[m1, r]区间内,可以不必再考虑[l, m1]区间;原因就是当f(m1) < f(m2)时,m1处于单调递增区间段,故f(l) < f(m1);
- 若f(m1) > f(m2),说明极值点位于[l, m2]区间内,可以不必再考虑[m2, r]区间;原因就是当f(m1) > f(m2)时,m2处于单调递减区间段,故f(m2) > f(r);
- 这样,每一轮迭代都会把查找范围限制在原来的2/3,直到最终逼近极值点,即l和r之间的差值接近无穷小;
- 三分查找的时间复杂度:O(log3n)�(���3�),二分查找的时间复杂度:O(log2n)�(���2�),尽管二者的复杂度级别一样,但是二分查找的效率更高,因为二分查找是在1/2的区域寻找值,而三分查找是在2/3的区域寻找值;
- 参考博客:三分查找(ternary search)及其示例 - 简书、二分查找和三分查找哪个快?算法复杂度与常数无关?复杂度分析的常见误区 - 知乎
2.3 代码演示
double three_point_search(double (*func)(double), double l, double r) {double m1, m2;int flag = 0; // flag = 0:func 函数为凸函数;flag = 1:func 函数为凹函数// 凹凸函数判断if (func((l + r) / 2.0) > (func(l) + func(r)) / 2.0 ) flag = 0;else flag = 1;#define EPSL 1e-6if (!flag) {while (fabs(r - l) > EPSL) {m1 = l + (r - l) / 3.0, m2 = r - (r - l) / 3.0;if (func(m1) < func(m2)) l = m1;else r = m2;}} else {while (fabs(r - l) > EPSL) {printf("l = %f, r = %f\n", l, r);m1 = l + (r - l) / 3.0, m2 = r - (r - l) / 3.0;if (func(m1) < func(m2)) r = m2;else l = m1;}}#undef EPSLreturn l;
}
3 哈希表 HashTable
3.1 介绍
基于数组的“随机访问”特性,其可以通过下标快速地找到对应位置的元素,然而这种通过`<int>`下标寻找`<任意类型>`元素的映射关系并不通用(映射关系:`<int>`→`<任意类型>`)。所以,为了拥有数组“快速访问”的特性,以及在查找元素过程中具有<`任意类型`>到`<任意类型>`的映射关系,哈希表就应运而生了。哈希表主要由**哈希函数** 和 **哈希冲突处理方法**两部分组成,其中**哈希函数**完成<`任意类型`>到`<int>`的映射(这儿用key-value来说明,key为输入,value为输出,即key到value的映射),但是这种映射关系并不唯一,即不同的key可能会有相同的value存在,若直接通过value来标记key的话,就会有覆盖现象发生,此时就会用到 **哈希冲突处理方法**。简单来讲,哈希表(Hash table,也叫散列表),是通过哈希函数将任意类型的数据转化成一个整型数字,然后用这个整型数字对数组长度取余,将其结果作为数组的下标,然后把这组数据存储到对应下标的数组空间(**数据存储过程**)。在使用哈希表进行数据查询时,就是再次通过哈希函数获取数组的下标,然后使用这个下标直接访问对应位置的数组元素,故哈希表查找数据的时间复杂度几乎为O(1)(**数据查找过程**)。
-
什么是哈希表(散列表)
哈希表就是通过哈希函数将输入映射到数组的某个位置,然后利用数组的“随机访问”特性进行快速查找;通过哈希函数映射值来存放数据的数组就是哈希表。
-
为什么要使用哈希表
在几乎为O(1)的时间复杂度内快速查找元素在数组中的位置。与一般查找不同,若直接在数组内查找某个元素,需要从头遍历一次数组,其时间复杂度为O(n);若使用二分查找,每次都需要将待查找区间缩小一半,其时间复杂度为O(logn);
-
哈希表、数组、链表的区别
为了具有数组“随机访问”的特性,在哈希表中引入了哈希函数,然而哈希函数的引入会出现哈希冲突,比如“如果两个字符串在哈希表中对应的位置相同怎么办?”,而数组的容量又是有限的,其中一种解决方案就是使用链表结构,在哈希表的每个入口挂一个链表,保存所有对应的字符串就OK了,此时的哈希表就是一种数组+链表组合的数据结构。
3.2 哈希(散列)函数
把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。这种转换是一种压缩映射,也就是,散列值的空间通常远小于输入的空间,不同的输入可能会散列成相同的输出,而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。
3.3 冲突处理方法
- 开放定值
- 再哈希|散列
- 拉链法
- 建立公共溢出区
哈希hash(散列)表结构详解_hash的结构-CSDN博客
Hash算法_bkdrhash acm-CSDN博客
3.4 代码演示
// 哈希函数:BKDRHash, 将 字符串类型 -> int
// 冲突处理:拉链法typedef struct Node {char *str;struct Node *next;
} Node;typedef struct HashTable {Node **data;int size;
} HashTable;Node *init_Node(char *str, Node *head) {Node *p = (Node *)malloc(sizeof(Node));p->str = strdup(str); // 深拷贝p->next = head; // 头插法return p;
}HashTable *init_hash(int n) {HashTable *h = (HashTable *)malloc(sizeof(HashTable));h->size = n << 1; // 哈希表的空间利用率,一般为70%~90%,当前利用率为50%h->data = (Node **)calloc(h->size, sizeof(Node *));return h;
}int BKDRHash(char *str) {int seed = 31, hash = 0;for (int i = 0; str[i]; i++) hash = hash * seed + str[i];return hash & 0x7fffffff;
}int insert(HashTable *h, char *str) {int hash = BKDRHash(str);int ind = hash % h->size;h->data[ind] = init_Node(str, h->data[ind]); // 拉链法return 1;
}int search(HashTable *h, char *str) {int hash = BKDRHash(str);int ind = hash % h->size;Node *p = h->data[ind];while (p && strcmp(p->str, str)) p = p->next;return p != NULL;
}void clear_node(Node *head) {if (head == NULL) return ;Node *p = head, *q;while (p != NULL) {q = p->next;free(p->str);free(p);p = q;}return ;
}void clear(HashTable *h) {if (h == NULL) return;for (int i = 0; i < h->size; i++) {clear_node(h->data[i]);}free(h->data);free(h);return ;
}
相关文章:

查找算法及哈希表
1 二分查找 1.1 重要概念 拟解决的问题:判断某个区间是否包含某个元素,无法确定区间中包含重复元素的具体位置;使用条件:查找的区间必须符合单调性;本质:采用分治思想,将某个单调区间一分为二…...

ELK分布式日志管理平台部署
目录 一、ELK概述 1、ELK概念: 2、其他数据收集工具: 3、ELK工作流程图: 4、ELK 的工作原理: 5、日志系统的特征: 二、实验部署: 1、ELK Elasticsearch 集群部署 2、安装 Elasticsearch-head 插件 …...

四、虚拟机网络配置
目录 1、VMware网卡配置模式 1.1 桥接模式 1.2 NAT模式 1.3 仅主机模式 2、编辑虚拟机的网络编辑器 3、编辑Window的虚拟网卡 4、修改IP地址为静态 4.1 查看网卡名字 4.2 编辑修改网卡IP地址的配置文件 4.3 重启网络: 4.…...

四、Lua循环
文章目录 一、while(循环条件)二、for(一)数值for(二)泛型for(三)repeat util 既然同为编程语言,那么控制逻辑里的循环就不能缺少,它可以帮助我们实现有规律的重复操作,而…...

生成对抗网络(GAN)手写数字生成
文章目录 一、前言二、前期工作1. 设置GPU(如果使用的是CPU可以忽略这步) 二、什么是生成对抗网络1. 简单介绍2. 应用领域 三、网络结构四、构建生成器五、构建鉴别器六、训练模型1. 保存样例图片2. 训练模型 七、生成动图 一、前言 我的环境࿱…...

LeetCode Hot100 31.下一个排列
题目: 整数数组的一个 排列 就是将其所有成员以序列或线性顺序排列。 例如,arr [1,2,3] ,以下这些都可以视作 arr 的排列:[1,2,3]、[1,3,2]、[3,1,2]、[2,3,1] 。 整数数组的 下一个排列 是指其整数的下一个字典序更大的排列…...

Redis主从与哨兵架构详解
目录 主从架构 主从环境搭建 主从复制流程 1. 全量复制 2. 部分复制 主从风暴 哨兵架构 概念 哨兵环境搭建 主从架构 主从环境搭建 1. 复制一份redis.conf文件, 修改下面几行配置 port 6380 pidfile /var/run/redis_6380.pid logfile "6380.log" dir /usr/…...

Linux:docker的数据管理(6)
数据管理操作*方便查看容器内产生的数据 *多容器间实现数据共享 两种管理方式数据卷 数据卷容器 1.数据卷 数据卷是一个供容器使用的特殊目录,位于容器中,可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻可见,并且更新数…...

深入理解Zookeeper系列-1.初识Zoookeeper
👏作者简介:大家好,我是爱吃芝士的土豆倪,24届校招生Java选手,很高兴认识大家📕系列专栏:Spring源码、JUC源码、Kafka原理、分布式技术原理🔥如果感觉博主的文章还不错的话ÿ…...

芯片技术探索:了解构芯片的设计与制造之旅
芯片技术探索:了解构芯片的设计与制造之旅 一、引言 随着现代科技的飞速发展,芯片作为信息技术的核心,已经渗透到我们生活的方方面面。从智能手机、电视、汽车到医疗设备和工业控制系统,芯片在各个领域都发挥着至关重要的作用。然而,对于大多数人来说,芯片仍然是一个神秘…...

STM32 超声波模块(HC-SR04)
HC-SR04介绍 典型工作电压:5v (如果你的超声波模块没有工作,可以看一下是不是电压不够)超小静态工作电流:<2mA 感应角度:<15 (超声波模块,是一个范围式的探…...

ELK+Filebeat
Filebeat概述 1.Filebeat简介 Filebeat是一款轻量级的日志收集工具,可以在非JAVA环境下运行。 因此,Filebeat常被用在非JAVAf的服务器上用于替代Logstash,收集日志信息。实际上,Filebeat几乎可以起到与Logstash相同的作用&…...

MySql之锁表、锁行解决方案
查询正在使用的表,没有跑业务,一般情况下是锁表了 show open tables where in_use > 0 ;查看进程,可以看到Command类型(Sleep为阻塞线程) show processlist;kill事务,kill 进程Id kill 8193583;其他 …...

2023年第十六届山东省职业院校技能大赛中职组“网络安全”赛项竞赛正式试题
第十六届山东省职业院校技能大赛中职组 “网络安全”赛项竞赛试题 目录 一、竞赛时间 二、竞赛阶段 三、竞赛任务书内容 (一)拓扑图 (二)A模块基础设施设置/安全加固(200分) (三…...

JAVA 整合 AWS S3(Amazon Simple Storage Service)文件上传,分片上传,删除,下载
依赖 因为aws需要发送请求上传、下载等api,所以需要加上httpclient相关的依赖 <dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk-s3</artifactId><version>1.11.628</version> </dependency&…...

记录:Unity脚本的编写9.0
目录 射线一些准备工作编写代码 突然发现好像没有写过关于射线的内容,我就说怎么总感觉好像少了什么东西(心虚 那就在这里写一下关于射线的内容吧,将在这里实现射线检测鼠标点击的功能 射线 射线是一种在Unity中检测碰撞器或触发器的方法&am…...

共享单车停放(简单的struct结构运用)
本来不想写这题的,但是想想最近沉迷玩雨世界,班长又问我这题,就草草写了一下 代码如下: #include<stdio.h> #include<math.h> struct parking{int distance;int remain;int speed;int time;int jud; }parking[50]; …...

【Java8系列07】Java8日期处理
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

为什么做CSGO搬砖的不直接去炒股呢?
首先,CS2并非只有一个交易平台,阿阳个人觉得像IGXE等交易平台一样是交易,况且我记得很早的时候我就开始用IGXE了,我记得最早的时候还是机器人发货,后来因为V社对于很多开箱网站的管控,所以让这种发货的方式…...

12月01日,每日信息差//阿里国际发布3款AI设计生态工具//美团买菜升级为“小象超市”//外国人永居证换新、6国游客免签来华
_灵感 🎖 阿里国际发布3款AI设计生态工具 🎄 AITO问界系列11月交付新车18827辆 🌍 美团买菜升级为“小象超市” 🌋 全球首个金融风控大模型国际标准出炉,由腾讯牵头制定 🎁 支付宝:支持外国人…...

ChatGPT探索:提示工程详解—程序员效率提升必备技能【文末送书】
文章目录 一.人工智能-ChatGPT1.1 ChatGPT简介1.2 ChatGPT探索:提示工程详解1.2 提示工程的优势 二.提示工程探索2.1 提示工程实例:2.2 英语学习助手2.3 Active-Prompt思维链(CoT)方法2.4 提示工程总结 三.文末推荐与福利3.1《Cha…...

Pytest做性能测试?
Pytest其实也是可以做性能测试或者基准测试的。是非常方便的。 可以考虑使用Pytest-benchmark类库进行。 安装pytest-benchmark 首先,确保已经安装了pytest和pytest-benchmark插件。可以使用以下命令安装插件: pip install pytest pytest-benchmark …...

Swagger各版本访问地址
2.9.x 访问地址: http://ip:port/{context-path}/swagger-ui.html 3.0.x 访问地址: http://ip:port/{context-path}/swagger-ui/index.html 3.0集成knife4j 访问地址: http://ip:port/{context-path}/doc.html...

docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor
docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor 文章目录 docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbordocker-compose私有镜像仓库harbor搭建镜像推送到私有仓库harbor docker-compose D…...

OpenTSDB(CVE-202035476)漏洞复现及利用
任务一: 复现环境中的命令注入漏洞。 任务二: 利用命令注入执行whoami,使用DNS外带技术获取结果 任务三:使用反弹shell,将漏洞环境中的shell反弹到宿主机或者vps服务器。 任务一: 1.搭建好环境 2.先去了…...

Maven无法拉取依赖/构建失败操作步骤(基本都能解决)
首先检查配置文件,确认配置文件没有问题(也可以直接用同事的配置文件(记得修改文件里的本地仓库地址)) 1.file->Invalidate Caches清除缓存重启(简单粗暴,但最有效) 2.刷新maven以及mvn clean,多刷几次,看看还有没有报红的依赖…...

【数据库】数据库并发控制的目标,可串行化序列的分析,并发控制调度器模型
数据库并发控制 专栏内容: 手写数据库toadb 本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。 本专栏会定期更…...

带头结点的双向循环链表
目录 带头结点的双向循环链表 1.存储定义 2.结点的创建 3.结点的初始化 4.尾插结点 5.尾删结点 6.头插结点 7.头删结点 8.查找并返回结点 9.在pos结点前插入结点 10.删除pos结点 11.打印链表 12.销毁链表 13.头插结点2.0版 14.尾插结点2.0版 前言: 当…...

2023年11月下旬大模型新动向集锦
2023年11月下旬大模型新动向集锦 2023.12.1版权声明:本文为博主chszs的原创文章,未经博主允许不得转载。 1、微软将向中国大陆开放Windows Copilot服务 据微软发布的消息,微软将在 2023 年 12 月 1 日面向中国大陆的企业和教育机构推出 We…...

有IP没有域名可以申请证书吗?
一、IP证书是什么? ip证书是用于公网ip地址的SSL证书,与我们通常所讲的SSL证书并无本质上的区别,但由于SSL证书通常颁发给域名,而组织机构需要公共ip地址的SSL证书,这类SSL证书就是我们所说的ip证书。ip证书具有安全、…...