19
19
20
20
> 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
21
21
22
+ ** C++版本**
22
23
``` cpp
23
24
// 二分搜索最常用模板
24
25
int search (vector<int >& nums, int target) {
@@ -40,6 +41,22 @@ int search(vector<int>& nums, int target) {
40
41
return -1;
41
42
}
42
43
```
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
+ ```
43
60
44
61
大部分二分查找类的题目都可以用这个模板,然后做一点特殊逻辑即可
45
62
@@ -72,6 +89,61 @@ int search(vector<int>& nums, int target) {
72
89
```
73
90
74
91
## 常见题目
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
+
75
147
76
148
### [ search-for-range] ( https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/ )
77
149
@@ -80,6 +152,65 @@ int search(vector<int>& nums, int target) {
80
152
81
153
思路:核心点就是找第一个 target 的索引,和最后一个 target 的索引,所以用两次二分搜索分别找第一次和最后一次的位置
82
154
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++版本**
83
214
``` cpp
84
215
vector<int > searchRange (vector<int >& nums, int target) {
85
216
if(nums.empty()) return {-1, -1};
@@ -170,6 +301,26 @@ bool searchMatrix(vector<vector<int>>& matrix, int target) {
170
301
> 假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
171
302
> 你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
172
303
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++版本**
173
324
``` cpp
174
325
int firstBadVersion (int n) {
175
326
int left = 1, right = n;
@@ -187,7 +338,22 @@ int firstBadVersion(int n) {
187
338
188
339
> 假设按照升序排序的数组在预先未知的某个点上进行了旋转( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
189
340
> 请找出其中最小的元素。
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
+ ```
190
355
356
+ ** C++版本**
191
357
``` cpp
192
358
int findMin (vector<int >& nums) {
193
359
if(nums.empty()) return 0;
@@ -236,6 +402,28 @@ int findMin(vector<int>& nums) {
236
402
> 搜索一个给定的目标值,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
237
403
> 你可以假设数组中不存在重复的元素。
238
404
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++版本**
239
427
``` cpp
240
428
int search (vector<int >& nums, int target) {
241
429
if(nums.empty()) return -1;
@@ -264,6 +452,30 @@ int search(vector<int>& nums, int target) {
264
452
265
453
> 面试时,可以直接画图进行辅助说明,空讲很容易让大家都比较蒙圈
266
454
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
+
267
479
### [ search-in-rotated-sorted-array-ii] ( https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/ )
268
480
269
481
> 假设按照升序排序的数组在预先未知的某个点上进行了旋转。
0 commit comments