Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit e8ff355

Browse files
二分查找
1 parent 4034b05 commit e8ff355

File tree

2 files changed

+283
-256
lines changed

2 files changed

+283
-256
lines changed

‎data_structure/二分查找.md

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
## List-binarysearch
2+
### 二分查找
3+
#### 解题步骤
4+
1. 确定二分左右边界
5+
2. 设计一个性质使得可以将区间划分成两段(要求的点在其中一段的端点)
6+
3. 区间更新
7+
#### 二分查找模板
8+
```
9+
bool check(int x) // 检查x是否满足某种性质
10+
int bsearch_1(int l, int r){
11+
while (l < r){
12+
int mid = l + r >> 1;
13+
if (check(mid)) r = mid;
14+
else l = mid + 1;
15+
}
16+
return l;
17+
}
18+
19+
int bsearch_2(int l, int r){
20+
while (l < r){
21+
int mid = l + r + 1>> 1;
22+
if (check(mid)) l = mid;
23+
else r = mid - 1;
24+
}
25+
return l;
26+
}
27+
```
28+
#### leetcode.704
29+
- 链接<https://leetcode.cn/problems/binary-search/>
30+
- leetcode解题代码
31+
```
32+
class Solution {
33+
public:
34+
int search(vector<int>& nums, int target) {
35+
int l = 0, r = nums.size() - 1;
36+
while (l < r){
37+
int mid = (l + r) / 2;
38+
if (nums[mid] >= target) r = mid;
39+
else l = mid + 1;
40+
}
41+
if (nums[l] == target) return l;
42+
return -1;
43+
}
44+
};
45+
```
46+
#### leetcode.278
47+
- 链接<https://leetcode.cn/problems/first-bad-version/>
48+
- leetcode解题代码
49+
```
50+
// The API isBadVersion is defined for you.
51+
// bool isBadVersion(int version);
52+
53+
class Solution {
54+
public:
55+
int firstBadVersion(int n) {
56+
long l = 1, r = n;
57+
while (l < r){
58+
int mid = (l + r) / 2;
59+
if (isBadVersion(mid)) r = mid;
60+
else l = mid + 1;
61+
}
62+
return l;// 返回的是第一个错误的版本
63+
}
64+
};
65+
```
66+
#### leetcode.35
67+
- 链接<https://leetcode.cn/problems/search-insert-position/>
68+
- leetcode解题代码
69+
```
70+
class Solution {
71+
public:
72+
int searchInsert(vector<int>& nums, int target) {
73+
int n = nums.size();
74+
if (target > nums[n - 1]) return n;
75+
int l = 0, r = n - 1;
76+
while (l < r){
77+
int mid = (l + r) / 2;
78+
if (nums[mid] >= target) r = mid;
79+
else l = mid + 1;
80+
}
81+
return l;
82+
}
83+
};
84+
```
85+
#### leetcode.69
86+
- 链接<https://leetcode.cn/problems/sqrtx/submissions/>
87+
- leetcode解题代码
88+
```
89+
class Solution {
90+
public:
91+
int mySqrt(int x) {
92+
if (x <= 1) return x;
93+
long l = 1, r = x;
94+
while (l < r){
95+
int mid = l + r + 1 >> 1;
96+
if (mid <= x / mid) l = mid;// 下取整,取第一个小于等于根号下x的值
97+
else r = mid - 1;
98+
}
99+
100+
return l;
101+
}
102+
};
103+
```
104+
#### leetcode.367
105+
- 链接<https://leetcode.cn/problems/valid-perfect-square/>
106+
- 注意:与上一题区别在于只是判断是否存在完全平方数,不需要上取整或者下取整求完全平方数,所以使用模板一或者模板二均可
107+
- leetcode解题代码
108+
```
109+
class Solution {
110+
public:
111+
bool isPerfectSquare(int num) {
112+
long l = 1, r = num;
113+
while (l < r){
114+
int mid = l + r + 1 >> 1;
115+
if (mid <= num / mid) l = mid;
116+
else r = mid - 1;
117+
}
118+
return r * r == num;
119+
}
120+
};
121+
```
122+
#### leetcode.34
123+
- 链接<https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/>
124+
- leetcode解题代码
125+
```
126+
class Solution {
127+
public:
128+
vector<int> searchRange(vector<int>& nums, int target) {
129+
if (nums.empty()) return {-1, -1};
130+
int l = 0, r = nums.size() - 1;
131+
while (l < r){
132+
int mid = l + r >> 1;
133+
// 找到>=target的第一个数
134+
if (nums[mid] >= target) r = mid;
135+
else l = mid + 1;
136+
}
137+
138+
if (nums[l] != target) return {-1, -1};
139+
int L = l;
140+
141+
l = 0, r = nums.size() - 1;
142+
while (l < r){
143+
int mid = l + r + 1 >> 1;
144+
// 找到<=target的第一个数
145+
if (nums[mid] <= target) l = mid;
146+
else r = mid - 1;
147+
}
148+
return {L, r};
149+
}
150+
};
151+
```
152+
#### leetcode.74
153+
- 链接<https://leetcode.cn/problems/search-a-2d-matrix/>
154+
- 解题思路:将二维矩阵展成一维数组,二分
155+
- 注意:矩阵下标(i,j)转化为一维数组下标
156+
- leetcode解题代码
157+
```
158+
class Solution {
159+
public:
160+
bool searchMatrix(vector<vector<int>>& matrix, int target) {
161+
if (matrix.empty()) return false;
162+
int n = matrix.size(), m = matrix[0].size();
163+
int l = 0, r = n * m - 1;
164+
while (l < r){
165+
int mid = l + r >> 1;
166+
// 将矩阵下标转换为数组下标
167+
if (matrix[mid / m][mid % m] >= target) r = mid;
168+
else l = mid + 1;
169+
}
170+
171+
if (matrix[l / m][l % m] == target) return true;
172+
return false;
173+
}
174+
};
175+
```
176+
#### leetcode.153
177+
- 链接<https://leetcode.cn/problems/find-minimum-in-rotated-sorted-array/>
178+
- 解题思路:找到数组的二段性(前段的值均大于数组的最后一位,后段的值均小于等于数组的最后一位,并且最小的点在后段的端点处)
179+
- leetcode解题代码
180+
```
181+
class Solution {
182+
public:
183+
int findMin(vector<int>& nums) {
184+
int l = 0, r = nums.size();
185+
while (l < r){
186+
int mid = l + r >> 1;
187+
if (nums[mid] <= nums.back()) r = mid;
188+
else l = mid + 1;
189+
}
190+
return nums[l];
191+
}
192+
};
193+
```
194+
#### leetcode.33
195+
- 链接<https://leetcode.cn/problems/search-in-rotated-sorted-array/>
196+
- 解题思路:由于没有二段性不能直接二分,先找到数组的最小值(参考上一题),找到目标值所在区间,在对应区间内二分找目标值
197+
- leetcode解题代码
198+
```
199+
class Solution {
200+
public:
201+
int search(vector<int>& nums, int target) {
202+
if (nums.empty()) return -1;
203+
// 找到最小值
204+
int l = 0, r = nums.size() - 1;
205+
while (l < r){
206+
int mid = (l + r) / 2;
207+
if (nums[mid] <= nums.back()) r = mid;
208+
else l = mid + 1;
209+
}
210+
// 判断目标值所在区间
211+
if (target <= nums.back()) r = nums.size() - 1;
212+
else l = 0, r --;
213+
// 在所在区间找目标值
214+
while (l < r){
215+
int mid = (l + r) / 2;
216+
if (nums[mid] >= target) r = mid;
217+
else l = mid + 1;
218+
}
219+
if (nums[l] == target) return l;
220+
return -1;
221+
}
222+
};
223+
```
224+
***
225+
下列题目没有二段性,但仍然可以通过二分每次缩小一般的搜索区间找到答案
226+
#### leetcode.162
227+
- 链接<https://leetcode.cn/problems/find-peak-element/>
228+
- 解题思路:如果二分的中点的值比中点右边的值小,那么右边一定存在峰值,同理,如果二分的中点的值比中点右边的值大,那么左边一定存在峰值
229+
- leetcode解题代码
230+
```
231+
class Solution {
232+
public:
233+
int findPeakElement(vector<int>& nums) {
234+
int l = 0, r = nums.size() - 1;
235+
while (l < r){
236+
int mid = l + r >> 1;
237+
// 说明左边一定有峰值
238+
if (nums[mid] > nums[mid + 1]) r = mid;
239+
else l = mid + 1;
240+
}
241+
return l;
242+
}
243+
};
244+
245+
class Solution {
246+
public:
247+
int findPeakElement(vector<int>& nums) {
248+
int l = 0, r = nums.size() - 1;
249+
while (l < r){
250+
int mid = l + r >> 1;
251+
// 说明右边一定有峰值
252+
if (nums[mid] < nums[mid + 1]) l = mid + 1;
253+
else r = mid;
254+
}
255+
return l;
256+
}
257+
};
258+
```
259+
#### leetcode.287
260+
- 链接<https://leetcode.cn/problems/find-the-duplicate-number/>
261+
- 解题思路:抽屉原理,n+1个苹果放进n个抽屉中必然有一个抽屉放了两个苹果,抽屉为数据范围n,苹果为数字总数n+1,对数据范围二分,记录二分中点左侧的数字总数,和左边数据范围对比,如果数字总数大于数据范围,说明重复数在左侧,右侧同理
262+
- leetcode解题代码
263+
```
264+
class Solution {
265+
public:
266+
int findDuplicate(vector<int>& nums) {
267+
int l = 1, r = nums.size();
268+
while (l < r){
269+
int mid = l + r >> 1;
270+
271+
int cnt = 0;
272+
for (auto c: nums){
273+
if (c >= l && c <= mid)
274+
cnt ++;
275+
}
276+
if (cnt > mid - l + 1) r = mid;
277+
else l = mid + 1;
278+
}
279+
return l;
280+
}
281+
};
282+
```
283+
解题参考:<https://www.acwing.com/>

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /