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 bf8d5fd

Browse files
committed
[yzx]1006:二分查找_python
1 parent f4061a7 commit bf8d5fd

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

‎TODO.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## v1
44

55
- [ ] 完善文档细节
6+
- [ ] python和C++实现
67
- [ ] 工程实现用到的算法解析
78
- [ ] 周赛计划
89
- [ ] 面试体系计划

‎basic_algorithm/binary_search.md‎

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
> 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
2121
22+
**C++版本**
2223
```cpp
2324
// 二分搜索最常用模板
2425
int search(vector<int>& nums, int target) {
@@ -40,6 +41,22 @@ int search(vector<int>& nums, int target) {
4041
return -1;
4142
}
4243
```
44+
**python3版本**
45+
```python
46+
class Solution:
47+
def search(self, nums: List[int], target: int) -> int:
48+
left = 0
49+
right = len(nums) - 1
50+
while left + 1 < right:
51+
mid = left + (right - left) // 2
52+
if nums[mid] == target: return mid
53+
elif nums[mid] < target: left = mid
54+
else: right = mid
55+
56+
if nums[left] == target: return left
57+
if nums[right] == target: return right
58+
return -1
59+
```
4360

4461
大部分二分查找类的题目都可以用这个模板,然后做一点特殊逻辑即可
4562

@@ -72,6 +89,61 @@ int search(vector<int>& nums, int target) {
7289
```
7390
7491
## 常见题目
92+
### [x的平方根](https://leetcode.cn/problems/sqrtx/)
93+
> 给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
94+
> 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
95+
> 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
96+
97+
**Python版本**
98+
```python
99+
class Solution:
100+
def mySqrt(self, x: int) -> int:
101+
if x == 0: return 0
102+
left, right = 1, x//2 + 1
103+
while left + 1 < right:
104+
mid = left + (right - left) // 2
105+
if mid * mid == x: return mid
106+
elif mid * mid < x: left = mid
107+
else: right = mid
108+
109+
if left * left > x: return left - 1
110+
elif right * right <= x: return right
111+
else: return left
112+
113+
```
114+
115+
### [猜数字大小](https://leetcode.cn/problems/guess-number-higher-or-lower/)
116+
> 猜数字游戏的规则如下:
117+
> 每轮游戏,我都会从 1 到 n 随机选择一个数字。 请你猜选出的是哪个数字。
118+
> 如果你猜错了,我会告诉你,你猜测的数字比我选出的数字是大了还是小了。
119+
> 你可以通过调用一个预先定义好的接口 int guess(int num) 来获取猜测结果,返回值一共有 3 种可能的情况(-1,1 或 0):
120+
121+
> -1:我选出的数字比你猜的数字小 pick < num
122+
123+
> 1:我选出的数字比你猜的数字大 pick > num
124+
125+
> 0:我选出的数字和你猜的数字一样。恭喜!你猜对了!pick == num
126+
127+
**Python版本**
128+
```python
129+
# The guess API is already defined for you.
130+
# @param num, your guess
131+
# @return -1 if my number is lower, 1 if my number is higher, otherwise return 0
132+
# def guess(num: int) -> int:
133+
134+
class Solution:
135+
def guessNumber(self, n: int) -> int:
136+
left, right = 1, n
137+
while left + 1 < right:
138+
mid = left + (right - left) // 2
139+
if guess(mid) == 0: return mid
140+
elif guess(mid) == -1: right = mid
141+
else: left = mid
142+
if guess(left) == 0: return left
143+
else: return right
144+
145+
```
146+
75147

76148
### [search-for-range](https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/)
77149

@@ -80,6 +152,65 @@ int search(vector<int>& nums, int target) {
80152
81153
思路:核心点就是找第一个 target 的索引,和最后一个 target 的索引,所以用两次二分搜索分别找第一次和最后一次的位置
82154

155+
**Python3版本**
156+
```python
157+
class Solution:
158+
def searchRange(self, nums: List[int], target: int) -> List[int]:
159+
if len(nums) == 0: return [-1, -1]
160+
161+
left, right = 0, len(nums) - 1
162+
while left + 1 < right:
163+
mid = left + (right - left) // 2
164+
if nums[mid] < target: left = mid
165+
elif nums[mid] > target: right = mid
166+
else:
167+
left = mid
168+
right = mid
169+
while left > 0 and nums[left-1] == target: left = left - 1
170+
while right < len(nums) - 1 and nums[right+1] == target: right = right + 1
171+
return [left, right]
172+
if nums[left] == target:
173+
if nums[right] == target: return [left, right]
174+
else: return [left, left]
175+
else:
176+
if nums[right] == target: return [right, right]
177+
else: return [-1, -1]
178+
```
179+
180+
```python
181+
class Solution:
182+
def searchRange(self, nums: List[int], target: int) -> List[int]:
183+
if len(nums) == 0: return [-1, -1]
184+
'''
185+
分解成找两次,找最左边一次,找最右边一次
186+
'''
187+
left = findTarget(nums, target, True)
188+
if left == -1: return [-1, -1]
189+
right = findTarget(nums, target, False)
190+
return [left, right]
191+
192+
def findTarget(nums, target, find_left):
193+
left, right = 0, len(nums) - 1
194+
while left + 1 < right:
195+
mid = left + (right - left) // 2
196+
if nums[mid] < target: left = mid
197+
elif nums[mid] > target: right = mid
198+
else:
199+
if find_left: right = mid
200+
else: left = mid
201+
202+
if find_left:
203+
if nums[left] == target: return left
204+
elif nums[right] == target: return right
205+
else: return -1
206+
else:
207+
if nums[right] == target: return right
208+
elif nums[left] == target: return left
209+
else: return -1
210+
211+
```
212+
213+
**C++版本**
83214
```cpp
84215
vector<int> searchRange(vector<int>& nums, int target) {
85216
if(nums.empty()) return {-1, -1};
@@ -170,6 +301,26 @@ bool searchMatrix(vector<vector<int>>& matrix, int target) {
170301
> 假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
171302
> 你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
172303
304+
**Python3版本**
305+
```python
306+
# The isBadVersion API is already defined for you.
307+
# def isBadVersion(version: int) -> bool:
308+
309+
class Solution:
310+
def firstBadVersion(self, n: int) -> int:
311+
left, right = 1, n
312+
313+
while left + 1 < right:
314+
mid = left + (right - left) // 2
315+
if not isBadVersion(mid): left = mid
316+
else: right = mid
317+
318+
if isBadVersion(left): return left
319+
else: return right
320+
321+
```
322+
323+
**C++版本**
173324
```cpp
174325
int firstBadVersion(int n) {
175326
int left = 1, right = n;
@@ -187,7 +338,22 @@ int firstBadVersion(int n) {
187338
188339
> 假设按照升序排序的数组在预先未知的某个点上进行了旋转( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
189340
> 请找出其中最小的元素。
341+
**Python版本**
342+
```python
343+
class Solution:
344+
def findMin(self, nums: List[int]) -> int:
345+
left, right = 0, len(nums) - 1
346+
if nums[left] <= nums[right]: return nums[left] # 说明还是升序排列
347+
348+
while left + 1 < right:
349+
mid = left + (right - left) // 2
350+
if nums[mid] >= nums[right]: left = mid
351+
else: right = mid
352+
353+
return min(nums[left], nums[right])
354+
```
190355

356+
**C++版本**
191357
```cpp
192358
int findMin(vector<int>& nums) {
193359
if(nums.empty()) return 0;
@@ -236,6 +402,28 @@ int findMin(vector<int>& nums) {
236402
> 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
237403
> 你可以假设数组中不存在重复的元素。
238404
405+
**Python版本**
406+
```python
407+
class Solution:
408+
def search(self, nums: List[int], target: int) -> int:
409+
left, right = 0, len(nums) - 1
410+
411+
while left + 1 < right:
412+
mid = left + (right - left) // 2
413+
if nums[mid] == target: return mid
414+
if nums[mid] > nums[left]:
415+
if target >= nums[left] and target <= nums[mid]: right = mid
416+
else: left = mid
417+
else:
418+
if target <= nums[right] and target >= nums[mid]: left = mid
419+
else: right = mid
420+
421+
if nums[left] == target: return left
422+
elif nums[right] == target: return right
423+
else: return -1
424+
```
425+
426+
**C++版本**
239427
```cpp
240428
int search(vector<int>& nums, int target) {
241429
if(nums.empty()) return -1;
@@ -264,6 +452,30 @@ int search(vector<int>& nums, int target) {
264452
265453
> 面试时,可以直接画图进行辅助说明,空讲很容易让大家都比较蒙圈
266454
455+
### [寻找峰值](https://leetcode.cn/problems/find-peak-element/)
456+
> 峰值元素是指其值严格大于左右相邻值的元素。
457+
> 给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
458+
> 你可以假设 nums[-1] = nums[n] = -∞ 。
459+
> 你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
460+
思路:规定了算法复杂度,那就是二分匹配法
461+
462+
**Python3版本**
463+
```python
464+
class Solution:
465+
def findPeakElement(self, nums: List[int]) -> int:
466+
left, right = 0, len(nums) - 1
467+
while left + 1 < right:
468+
mid = left + (right - left) // 2
469+
if nums[mid] < nums[mid+1]: left = mid
470+
else: right = mid
471+
472+
if nums[left] < nums[right]: return right
473+
else: return left
474+
```
475+
476+
**前面几道题说明了,二分匹配中,不一定直接对比mid和target, left和mid, mid本身, mid和相邻(mid+1),都是能做compare的。**
477+
478+
267479
### [search-in-rotated-sorted-array-ii](https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/)
268480

269481
> 假设按照升序排序的数组在预先未知的某个点上进行了旋转。

0 commit comments

Comments
(0)

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