数据结构入门:数组与二分查找(LeetCode704)
2026/9/3 21:03:24 网站建设 项目流程

一、数据结构基本介绍

什么是数据结构

数据结构,是计算机中组织、存储和管理数据的一套方式。现实世界里我们会把物品分类存放,方便查找、取用;在程序当中,数据同样需要合理的组织方式,这就是数据结构。

程序处理的本质就是对数据做操作:存储、查询、插入、删除、修改。不同的数据结构,在完成同样操作时,消耗的时间和内存是不一样的。学习数据结构,核心目的就是根据业务场景,选择合适的数据结构,优化程序的执行效率。

数据结构的分类

数据结构可以分为两大类别:线性结构与非线性结构。

1. 线性结构
数据元素之间是一对一的关系,排成一条直线。
常见:数组、链表、栈、队列。

数组:连续内存,支持下标随机访问;

链表:离散内存,依靠指针串联;

栈:后进先出(LIFO);

队列:先进先出(FIFO)。

2. 非线性结构
元素之间是一对多、多对多的关系。
常见:树、图、哈希表。

树:一对多,例如二叉树;

图:多对多,用来表示网络关系。

算法与数据结构的关系

数据结构是数据存放的容器,算法是处理数据的方法,二者相辅相成。
举个例子:在有序数组中查找目标值。

如果使用暴力遍历,从头到尾逐个对比,时间复杂度 O(n);

如果使用二分查找算法,每次直接排除一半数据,时间复杂度优化到 O(\log n)。
数据结构提供存储载体,算法负责高效操作数据。

学习顺序:先掌握基础线性结构(数组、链表),再学习栈、队列,之后再学习树、图等复杂结构。

二、数组基本概念

数组的定义

数组是一种连续的、固定大小的线性数据结构,在内存中开辟一块连续的存储空间,存放一组相同类型的数据。

数组核心特性

1. 内存连续
数组的所有元素在内存地址上是紧挨着的,没有空隙。这是数组最重要的特点。

正因为内存连续,数组可以通过下标直接定位元素,实现随机访问,访问任意下标元素的时间复杂度为 O(1)。

2. 下标从0开始
绝大多数编程语言(C/C++、Python、Java)数组下标起始为0。
数组第一个元素下标为0,第二个下标为1,以此类推。
对于长度为n的数组,合法下标范围是 0 \sim n-1。

注意:下标不能越界,如果访问下标等于数组长度,就会发生数组越界错误。

3. 长度固定
静态数组一旦创建,数组的总长度就不能改变。
如果想要存放更多元素,只能重新开辟一块更大的内存空间,把旧数组的数据复制过去。Python中的list虽然可以动态append,底层本质也是数组扩容机制。

数组与二分查找的关系

二分查找能够生效,前提条件是数组必须有序。
数组拥有随机访问能力,我们可以快速拿到中间位置的元素,不断缩小查找区间。如果是无序数组,无法使用二分查找,只能暴力遍历。
LeetCode704题目给出的就是升序数组,正好适合二分查找。

三、二分查找两种区间写法解题思路

本题为有序数组的目标值查找,利用二分查找可以将时间复杂度优化至 O(log n)。根据区间定义不同,分为左闭右闭和左闭右开两种标准写法,核心逻辑为不断缩小查找区间,直至找到目标或区间为空。

一、写法一:左闭右闭区间 [left, right]

1. 区间定义

查找区间为 左右边界均包含 的有效下标区间。
初始化:左指针 left = 0 ,右指针 right = len(nums) - 1 ,区间内所有下标都是合法查找范围。

2. 循环条件

循环条件设置<= right 。 原因:当 left == right 时,区间内仍保留一个有效元素,需要进入循环判断;只有 left > right` 时,区间彻底为空,查找结束。

3. 区间收缩逻辑

每次取中间位置 mid = left + (right - left) // 2 ,避免数值溢出:

1. 若 nums[< target :目标值在右侧区间,mid 位置已排除,更新左边界 left = mid + 1

2. 若 nums[mid] > target :目标值在左侧区间,mid 位置已排除,更新右边界 right = mid - 1

3. 若 nums[mid] == target :找到目标元素,直接返回当前下标 mid

4. 结果处理

循环正常退出说明区间内无目标值,返回 -1。

复杂度

时间复杂度:O(log n),每次查找区间长度减半

空间复杂度:O(1),仅使用常数变量



二、写法二:左闭右开区间 [left, right)

1. 区间定义

查找区间为 包含左边界、不包含右边界。
初始化:左指针 left = 0 ,右指针 right = len(nums) ,right 为数组边界外下标,不属于查找区间。

2. 循环条件

循环条件设置为 while left< right 。
原因:左、右指针相等时,区间 [left, right) 为空,无元素可判断,直接结束循环。

3. 区间收缩逻辑

同样取中间位置 mid = left + (right - left) // 2 :

1. 若 nums[mid]< target :目标在右侧,更新左边界 left = mid + 1

2. 若 nums[mid] > target :目标在左侧,因右边界为开区间,mid 本身不在区间内,直接更新右边界 right = mid

3. 若 nums[mid] == target :找到目标元素,返回下标 mid

4. 结果处理

循环结束未匹配到目标值,返回 -1。

复杂度

时间复杂度:O(log n)

空间复杂度:O(1)



总结

两种写法核心区别由区间定义决定,三者必须统一:

1. 左闭右闭: right=len-<=right 、 right=mid-1

2. 左闭右开: right=len <right 、 right=mid`
两种算法效率完全一致,仅边界处理逻辑不同。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询