【数据结构与算法-Day 36】查找算法入门:从顺序查找的朴素到二分查找的惊艳
Langchain系列文章目录
01-玩转LangChain:从模型调用到Prompt模板与输出解析的完整指南
02-玩转 LangChain Memory 模块:四种记忆类型详解及应用场景全覆盖
03-全面掌握 LangChain:从核心链条构建到动态任务分配的实战指南
04-玩转 LangChain:从文档加载到高效问答系统构建的全程实战
05-玩转 LangChain:深度评估问答系统的三种高效方法(示例生成、手动评估与LLM辅助评估)
06-从 0 到 1 掌握 LangChain Agents:自定义工具 + LLM 打造智能工作流!
07-【深度解析】从GPT-1到GPT-4:ChatGPT背后的核心原理全揭秘
08-【万字长文】MCP深度解析:打通AI与世界的“USB-C”,模型上下文协议原理、实践与未来
Python系列文章目录
PyTorch系列文章目录
机器学习系列文章目录
深度学习系列文章目录
Java系列文章目录
JavaScript系列文章目录
Python系列文章目录
Go语言系列文章目录
Docker系列文章目录
数据结构与算法系列文章目录
01-【数据结构与算法-Day 1】程序世界的基石:到底什么是数据结构与算法?
02-【数据结构与算法-Day 2】衡量代码的标尺:时间复杂度与大O表示法入门
03-【数据结构与算法-Day 3】揭秘算法效率的真相:全面解析O(n^2), O(2^n)及最好/最坏/平均复杂度
04-【数据结构与算法-Day 4】从O(1)到O(n²),全面掌握空间复杂度分析
05-【数据结构与算法-Day 5】实战演练:轻松看懂代码的时间与空间复杂度
06-【数据结构与算法-Day 6】最朴素的容器 - 数组(Array)深度解析
07-【数据结构与算法-Day 7】告别数组束缚,初识灵活的链表 (Linked List)
08-【数据结构与算法-Day 8】手把手带你拿捏单向链表:增、删、改核心操作详解
09-【数据结构与算法-Day 9】图解单向链表:从基础遍历到面试必考的链表反转
10-【数据结构与算法-Day 10】双向奔赴:深入解析双向链表(含图解与代码)
11-【数据结构与算法-Day 11】从循环链表到约瑟夫环,一文搞定链表的终极形态
12-【数据结构与算法-Day 12】深入浅出栈:从“后进先出”原理到数组与链表双实现
13-【数据结构与算法-Day 13】栈的应用:从括号匹配到逆波兰表达式求值,面试高频考点全解析
14-【数据结构与算法-Day 14】先进先出的公平:深入解析队列(Queue)的核心原理与数组实现
15-【数据结构与算法-Day 15】告别“假溢出”:深入解析循环队列与双端队列
16-【数据结构与算法-Day 16】队列的应用:广度优先搜索(BFS)的基石与迷宫寻路实战
17-【数据结构与算法-Day 17】揭秘哈希表:O(1)查找速度背后的魔法
18-【数据结构与算法-Day 18】面试必考!一文彻底搞懂哈希冲突四大解决方案:开放寻址、拉链法、再哈希
19-【数据结构与算法-Day 19】告别线性世界,一文掌握树(Tree)的核心概念与表示法
20-【数据结构与算法-Day 20】从零到一掌握二叉树:定义、性质、特殊形态与存储结构全解析
21-【数据结构与算法-Day 21】精通二叉树遍历(上):前序、中序、后序的递归与迭代实现
22-【数据结构与算法-Day 22】玩转二叉树遍历(下):广度优先搜索(BFS)与层序遍历的奥秘
23-【数据结构与算法-Day 23】为搜索而生:一文彻底搞懂二叉搜索树 (BST) 的奥秘
24-【数据结构与算法-Day 24】平衡的艺术:图解AVL树,彻底告别“瘸腿”二叉搜索树
25-【数据结构与算法-Day 25】工程中的王者:深入解析红黑树 (Red-Black Tree)
26-【数据结构与算法-Day 26】堆:揭秘优先队列背后的“特殊”完全二叉树
27-【数据结构与算法-Day 27】堆的应用:从堆排序到 Top K 问题,一文彻底搞定!
28-【数据结构与算法-Day 28】字符串查找的终极利器:深入解析字典树 (Trie / 前缀树)
29-【数据结构与算法-Day 29】从社交网络到地图导航,一文带你入门终极数据结构:图
30-【数据结构与算法-Day 30】图的存储:邻接矩阵 vs 邻接表,哪种才是最优选?
31-【数据结构与算法-Day 31】图的遍历:深度优先搜索 (DFS) 详解,一条路走到黑的智慧
32-【数据结构与算法-Day 32】掌握广度优先搜索 (BFS),轻松解决无权图最短路径问题
33-【数据结构与算法-Day 33】最小生成树之 Prim 算法:从零构建通信网络
34-【数据结构与算法-Day 34】最小生成树之 Kruskal 算法:从边的视角构建最小网络
35-【数据结构与算法-Day 35】拓扑排序:从依赖关系到关键路径的完整解析
36-【数据结构与算法-Day 36】查找算法入门:从顺序查找的朴素到二分查找的惊艳
文章目录
- Langchain系列文章目录
- Python系列文章目录
- PyTorch系列文章目录
- 机器学习系列文章目录
- 深度学习系列文章目录
- Java系列文章目录
- JavaScript系列文章目录
- Python系列文章目录
- Go语言系列文章目录
- Docker系列文章目录
- 数据结构与算法系列文章目录
- 摘要
- 一、初识查找算法
-
- 1.1 什么是查找?
- 1.2 为什么查找算法如此重要?
- 1.3 查找算法的分类
- 二、最朴素的策略 —— 顺序查找 (Sequential Search)
-
- 2.1 原理剖析:一往无前的“地毯式”搜索
- 2.2 图解原理
- 2.3 代码实现
- 2.4 性能分析
-
- 2.4.1 时间复杂度
- 2.4.2 空间复杂度
- 2.5 优缺点与应用场景
- 三、效率的飞跃 —— 二分查找 (Binary Search)
-
- 3.1 核心前提:有序性
- 3.2 原理剖析:不断缩小的“包围圈”
- 3.3 图解原理
- 3.4 代码实现:递归与非递归
-
- 3.4.1 非递归(迭代)实现 (推荐)
- 3.4.2 递归实现
- 3.5 性能分析
-
- 3.5.1 时间复杂度
- 3.5.2 空间复杂度
- 3.6 关键难点:边界条件处理
-
- 3.6.1 `while` 循环条件:`left <= right` 还是 `left < right`?
- 3.6.2 中点计算:`mid = (left + right) / 2` 的潜在问题
- 3.6.3 区间更新:`right = mid` 还是 `right = mid - 1`?
- 四、顺序查找 vs. 二分查找:全方位对比
- 五、总结
摘要
查找,是计算机科学中最基础也最核心的操作之一。无论是在浩如烟海的数据库中定位一条记录,还是在小小的数组中寻找一个特定值,查找算法都扮演着至关重要的角色。一个高效的查找策略能让程序性能产生质的飞跃。本篇文章作为查找算法系列的开篇,将带领大家从最直观、最朴素的顺序查找出发,逐步过渡到效率惊人、面试频率极高的二分查找。我们将深入剖析它们的底层原理、代码实现、性能优劣,并着重攻克二分查找中令人头疼的边界条件问题,为您打下坚实的查找算法基础。
一、初识查找算法
在深入具体算法之前,我们首先需要建立对“查找”这一概念的宏观认知。
1.1 什么是查找?
查找(Searching),顾名思义,就是在数据集合中寻找是否存在某个特定元素(称为“目标”或“键”),如果存在,则返回其位置或相关信息;如果不存在,则返回一个表示“未找到”的信号。
这个过程在生活中无处不在:
- 在图书馆找书:你拿着书名,在一排排书架上寻找,这就是一个查找过程。
- 查字典:你想知道某个字的含义,通过部首或拼音在字典中定位,这也是查找。
- 手机通讯录:输入联系人姓名的部分拼音,手机会筛选出匹配的联系人,这背后同样是查找算法在工作。
在计算机世界里,数据集合通常是数组、链表、树、图等数据结构。
1.2 为什么查找算法如此重要?
查找是大多数复杂应用的基础构件。其重要性体现在:
- 性能瓶颈:数据处理的核心往往是“增删改查”。其中,“查”的频率通常最高。一个低效的查找算法可能成为整个系统的性能瓶颈。
- 功能实现:许多高级功能都依赖于快速查找。例如,数据库的索引系统本质上就是为了加速查找;搜索引擎的核心是根据关键词在海量网页中进行高效查找。
- 算法基础:查找是许多其他算法(如排序、图算法等)的子过程。理解查找是深入学习更高级算法的前提。
1.3 查找算法的分类
根据数据结构的组织形式,查找算法大致可以分为:
- 基于线性结构的查找:在数组、链表等线性数据结构上进行查找。例如本文将要介绍的顺序查找和二分查找。
- 基于树形结构的查找:在二叉搜索树、AVL树、红黑树等结构上进行查找,效率极高。
- 基于哈希表的查找:通过哈希函数直接计算目标位置,理想情况下时间复杂度可达 O ( 1 ) O(1) O(1)。
本篇我们将聚焦于最基础的线性结构查找:顺序查找与二分查找。
二、最朴素的策略 —— 顺序查找 (Sequential Search)
顺序查找,也称线性查找(Linear Search),是最简单、最直观的查找算法。它的思想朴素得就像你在一条队伍里从头到尾挨个询问,直到找到你要找的人为止。
2.1 原理剖析:一往无前的“地毯式”搜索
顺序查找的策略非常简单:
- 从数据集合的第一个元素开始。
- 将当前元素与目标值进行比较。
- 如果相等,则查找成功,返回当前元素的索引。
- 如果不相等,则移动到下一个元素,重复步骤2。
- 如果遍历完所有元素仍未找到目标值,则查找失败,返回一个特殊值(如 -1)。
这种方法不对数据有任何要求,无论数据是无序的还是有序的,它都能正常工作。
2.2 图解原理
我们可以用一个简单的流程图来展示顺序查找的过程。
graph TDA[开始] --> B{i = 0};B --> C{i < 数组长度?};C -- 是 --> D{数组[i] == 目标值?};C -- 否 --> G[查找失败, 返回-1];D -- 是 --> E[查找成功, 返回 i];D -- 否 --> F{i++};F --> C;E --> H[结束];G --> H;style A fill:#f9f,stroke:#333,stroke-width:2pxstyle H fill:#f9f,stroke:#333,stroke-width:2px
2.3 代码实现
下面是顺序查找在 Java 中的一个典型实现。
/*** 顺序查找(线性查找)* @param arr 待查找的数组* @param target 要查找的目标值* @return 如果找到,返回目标值的索引;否则,返回 -1*/
public class SequentialSearch {public