Skip to content

Commit d47c6ce

Browse files
committed
更新目录章节链接
1. 二分查找知识内容优化 2. 更新目录章节链接
1 parent d635c34 commit d47c6ce

10 files changed

+402
-314
lines changed

Assets/Origins/Categories-List.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
###### 0217. 存在重复元素、0136. 只出现一次的数字、0056. 合并区间、0179. 最大数、0384. 打乱数组、剑指 Offer 45. 把数组排成最小的数
5858

5959

60-
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/02.Array-Binary-Search-List.md)
60+
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/03.Array-Binary-Search-List.md)
6161

6262
#### 二分下标题目
6363

Assets/Origins/Interview-100-List.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,7 @@
3838

3939
###### 0136. 只出现一次的数字、0056. 合并区间、0179. 最大数
4040

41-
42-
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/02.Array-Binary-Search-List.md)
41+
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/03.Array-Binary-Search-List.md)
4342

4443
#### 二分下标题目
4544

@@ -193,4 +192,3 @@
193192
#### 思维锻炼题目
194193

195194
###### 0031. 下一个排列、0470. 用 Rand7() 实现 Rand10()
196-

Assets/Origins/Interview-200-List.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,7 @@
5050

5151
###### 0136. 只出现一次的数字、0056. 合并区间、0179. 最大数、0384. 打乱数组、剑指 Offer 45. 把数组排成最小的数
5252

53-
54-
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/02.Array-Binary-Search-List.md)
53+
### [二分查找题目](../../Contents/01.Array/03.Array-Binary-Search/03.Array-Binary-Search-List.md)
5554

5655
#### 二分下标题目
5756

Assets/Origins/README-Catalogue-List.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,9 @@
2828
- [基数排序](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/02.Array-Sort/10.Array-Radix-Sort.md)
2929
- [数组排序题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/02.Array-Sort/11.Array-Sort-List.md)
3030
- 二分查找
31-
- [二分查找知识](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/03.Array-Binary-Search/01.Array-Binary-Search.md)
32-
- [二分查找题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/03.Array-Binary-Search/02.Array-Binary-Search-List.md)
31+
- [二分查找知识(一)](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/03.Array-Binary-Search/01.Array-Binary-Search-01.md)
32+
- [二分查找知识(二)](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/03.Array-Binary-Search/02.Array-Binary-Search-02.md)
33+
- [二分查找题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/03.Array-Binary-Search/03.Array-Binary-Search-List.md)
3334
- 数组双指针
3435
- [数组双指针知识](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/04.Array-Two-Pointers/01.Array-Two-Pointers.md)
3536
- [数组双指针题目](https://github.com/itcharge/LeetCode-Py/blob/main/Contents/01.Array/04.Array-Two-Pointers/02.Array-Two-Pointers-List.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
## 1. 二分查找算法介绍
2+
3+
### 1.1 二分查找算法简介
4+
5+
> **二分查找算法(Binary Search Algorithm)**:也叫做折半查找算法、对数查找算法,是一种用于在有序数组中查找特定元素的高效搜索算法。
6+
7+
二分查找的基本算法思想为:通过确定目标元素所在的区间范围,反复将查找范围减半,直到找到元素或找不到该元素为止。
8+
9+
### 1.2 二分查找算法步骤
10+
11+
以下是二分查找算法的基本步骤:
12+
13+
1. **初始化**:首先,确定要查找的有序数据集合。可以是一个数组或列表,确保其中的元素按照升序或者降序排列。
14+
2. **确定查找范围**:将整个有序数组集合的查找范围确定为整个数组范围区间,即左边界 $left$ 和右边界 $right$。
15+
3. **计算中间元素**:根据 $mid = \lfloor (left + right) / 2 \rfloor$ 计算出中间元素下标位置 $mid$。
16+
4. **比较中间元素**:将目标元素 $target$ 与中间元素 $nums[mid]$ 进行比较:
17+
1. 如果 $target == nums[mid]$,说明找到 $target$,因此返回中间元素的下标位置 $mid$。
18+
2. 如果 $target < nums[mid]$,说明目标元素在左半部分($[left, mid - 1]$),更新右边界为中间元素的前一个位置,即 $right = mid - 1$。
19+
3. 如果 $target > nums[mid]$,说明目标元素在右半部分($[mid + 1, right]$),更新左边界为中间元素的后一个位置,即 $left = mid + 1$。
20+
21+
5. 重复步骤 $3 \sim 4$,直到找到目标元素时返回中间元素下标位置,或者查找范围缩小为空(左边界大于右边界),表示目标元素不存在,此时返回 $-1$。
22+
23+
举个例子来说,以在有序数组 $[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]$ 中查找目标元素 $6$ 来说,使用二分查找算法的步骤如下:
24+
25+
1. **确定查找范围**:初始时左边界 $left$ 为 $0$(数组的起始位置),$right$ 为 $10$(数组的末尾位置)。此时查找范围为 $[0, 10]$。
26+
2. **计算中间元素**:中间元素下标位置为 $5$,对应元素为 $nums[5] == 5$。
27+
3. **比较中间元素**:因为 $6 > nums[5]$,所以目标元素可能在右半部分,更新左边界为中间元素的后一个位置,即 $left = 5$。此时查找范围为 $[5, 10]$。
28+
4. **计算中间元素**:中间元素下标位置为 $7$,对应元素为 $nums[7] == 7$。
29+
5. **比较中间元素**:因为 $6 < nums[7]$,所以目标元素可能在左半部分,更新右边界为中间元素的前一个位置,即 $right = 6$。此时查找范围为 $[5, 6]$。
30+
6. **计算中间元素**:中间元素下标位置为 $5$,对应元素为 $nums[5] == 5$。
31+
7. **比较中间元素**:因为 $5 == nums[5]$,正好是我们正在查找的目标元素,此时返回中间元素的下标位置,算法结束。
32+
33+
于是我们发现,对于一个长度为 $10$ 的有序数组,我们只进行了 $3$ 次查找就找到了目标元素。而如果是按照顺序依次遍历数组,则在最坏情况下,我们可能需要查找 $10$ 次才能找到目标元素。
34+
35+
::: tabs#BinarySearch
36+
37+
@tab <1>
38+
39+
![二分查找算法 1](https://qcdn.itcharge.cn/images/20230906133729.png)
40+
41+
@tab <2>
42+
43+
![二分查找算法 2](https://qcdn.itcharge.cn/images/20230906133742.png)
44+
45+
@tab <3>
46+
47+
![二分查找算法 3](https://qcdn.itcharge.cn/images/20230906133758.png)
48+
49+
@tab <4>
50+
51+
![二分查找算法 4](https://qcdn.itcharge.cn/images/20230906133809.png)
52+
53+
@tab <5>
54+
55+
![二分查找算法 5](https://qcdn.itcharge.cn/images/20230906133820.png)
56+
57+
@tab <6>
58+
59+
![二分查找算法 6](https://qcdn.itcharge.cn/images/20230906133830.png)
60+
61+
@tab <7>
62+
63+
![二分查找算法 7](https://qcdn.itcharge.cn/images/20230906133839.png)
64+
65+
@tab <8>
66+
67+
![二分查找算法 8](https://qcdn.itcharge.cn/images/20230906133848.png)
68+
69+
:::
70+
71+
### 1.2 二分查找算法思想
72+
73+
二分查找算法是经典的 **「减而治之」** 的思想。
74+
75+
这里的 **「减」** 是减少问题规模的意思,**「治」** 是解决问题的意思。**「减」****「治」** 结合起来的意思就是 **「排除法解决问题」**。即:**每一次查找,排除掉一定不存在目标元素的区间,在剩下可能存在目标元素的区间中继续查找。**
76+
77+
每一次通过一些条件判断,将待搜索的区间逐渐缩小,以达到「减少问题规模」的目的。而于问题的规模是有限的,经过有限次的查找,最终会查找到目标元素或者查找失败。
78+
79+
## 2. 简单二分查找
80+
81+
下面通过一个简单的例子来讲解下二分查找的思路和代码。
82+
83+
- 题目链接:[704. 二分查找](https://leetcode.cn/problems/binary-search/)
84+
85+
### 2.1 题目大意
86+
87+
**描述**:给定一个升序的数组 $nums$,和一个目标值 $target$。
88+
89+
**要求**:返回 $target$ 在数组中的位置,如果找不到,则返回 $-1$。
90+
91+
**说明**
92+
93+
- 你可以假设 $nums$ 中的所有元素是不重复的。
94+
- $n$ 将在 $[1, 10000]$ 之间。
95+
- $nums$ 的每个元素都将在 $[-9999, 9999]$之间。
96+
97+
**示例**
98+
99+
```python
100+
输入: nums = [-1,0,3,5,9,12], target = 9
101+
输出: 4
102+
解释: 9 出现在 nums 中并且下标为 4
103+
104+
105+
输入: nums = [-1,0,3,5,9,12], target = 2
106+
输出: -1
107+
解释: 2 不存在 nums 中因此返回 -1
108+
```
109+
110+
### 2.2 解题思路
111+
112+
#### 思路 1:二分查找
113+
114+
1. 设定左右边界为数组两端,即 $left = 0$,$right = len(nums) - 1$,代表待查找区间为 $[left, right]$(左闭右闭区间)。
115+
2. 取两个节点中心位置 $mid$,先比较中心位置值 $nums[mid]$ 与目标值 $target$ 的大小。
116+
1. 如果 $target == nums[mid]$,则返回中心位置。
117+
2. 如果 $target > nums[mid]$,则将左节点设置为 $mid + 1$,然后继续在右区间 $[mid + 1, right]$ 搜索。
118+
3. 如果 $target < nums[mid]$,则将右节点设置为 $mid - 1$,然后继续在左区间 $[left, mid - 1]$ 搜索。
119+
3. 如果左边界大于右边界,查找范围缩小为空,说明目标元素不存在,此时返回 $-1$。
120+
121+
#### 思路 1:代码
122+
123+
```python
124+
class Solution:
125+
def search(self, nums: List[int], target: int) -> int:
126+
left, right = 0, len(nums) - 1
127+
128+
# 在区间 [left, right] 内查找 target
129+
while left <= right:
130+
# 取区间中间节点
131+
mid = (left + right) // 2
132+
# 如果找到目标值,则直接返回中心位置
133+
if nums[mid] == target:
134+
return mid
135+
# 如果 nums[mid] 小于目标值,则在 [mid + 1, right] 中继续搜索
136+
elif nums[mid] < target:
137+
left = mid + 1
138+
# 如果 nums[mid] 大于目标值,则在 [left, mid - 1] 中继续搜索
139+
else:
140+
right = mid - 1
141+
# 未搜索到元素,返回 -1
142+
return -1
143+
```
144+
145+
#### 思路 1:复杂度分析
146+
147+
- **时间复杂度**:$O(\log n)$。
148+
- **空间复杂度**:$O(1)$。

0 commit comments

Comments
 (0)