|
2 | 2 |
|
3 | 3 | 给一个**有序数组**和目标值,找第一次/最后一次/任何一次出现的索引,时间复杂度 O(logN)。
|
4 | 4 |
|
| 5 | +注意,不必递归,而是循环left right。 |
| 6 | + |
5 | 7 | ## 模板
|
6 | 8 |
|
7 |
| -常用的二分搜索模板有如下三种形式: |
| 9 | +常用的二分搜索模板有如下三种形式:【只需记忆1和3,while里left不加1,则if else时加减1;否则if else不加减1。】 |
| 10 | +注意输出也有些需要后处理的形式。 |
8 | 11 |
|
9 | 12 | 
|
10 | 13 |
|
@@ -37,7 +40,7 @@ class Solution:
|
37 | 40 | return -1
|
38 | 41 | ```
|
39 | 42 |
|
40 |
| -- 如果是最简单的二分搜索,不需要找第一个、最后一个位置,或者是没有重复元素,可以使用模板 1,代码更简洁。同时,如果搜索失败,left 是第一个大于 target 的索引,right 是最后一个小于 target 的索引。 |
| 43 | +- 【纯查找,模板1的实现】如果是最简单的二分搜索,不需要找第一个、最后一个位置,或者是没有重复元素,可以使用模板 1,代码更简洁。同时,如果搜索失败,left 是第一个大于 target 的索引,right 是最后一个小于 target 的索引。 |
41 | 44 |
|
42 | 45 | ```Python
|
43 | 46 | class Solution:
|
@@ -88,43 +91,36 @@ class Solution:
|
88 | 91 |
|
89 | 92 | ```Python
|
90 | 93 | class Solution:
|
91 |
| - def searchRange(self, nums, target): |
92 |
| - Range = [-1, -1] |
93 |
| - if len(nums) == 0: |
94 |
| - return Range |
| 94 | + def searchRange(self, nums: List[int], target: int) -> List[int]: |
| 95 | + result = [-1, -1] |
| 96 | + if not nums: return result |
95 | 97 |
|
96 | 98 | l, r = 0, len(nums) - 1
|
97 | 99 | while l + 1 < r:
|
98 | 100 | mid = l + (r - l) // 2
|
99 |
| - if nums[mid] < target: |
| 101 | + if nums[mid] < target: # 第一个位置,小于号 |
100 | 102 | l = mid
|
101 | 103 | else:
|
102 | 104 | r = mid
|
103 |
| - |
104 |
| - if nums[l] == target: |
105 |
| - Range[0] = l |
106 |
| - elif nums[r] == target: |
107 |
| - Range[0] = r |
108 |
| - else: |
109 |
| - return Range |
110 |
| - |
| 105 | + if nums[l] == target: result[0] = l |
| 106 | + elif nums[r] == target: result[0] = r |
| 107 | + else: return result |
| 108 | + |
111 | 109 | l, r = 0, len(nums) - 1
|
112 | 110 | while l + 1 < r:
|
113 | 111 | mid = l + (r - l) // 2
|
114 |
| - if nums[mid] <= target: |
| 112 | + if nums[mid] <= target: # 最后一个位置,小于等于号 |
115 | 113 | l = mid
|
116 | 114 | else:
|
117 | 115 | r = mid
|
118 |
| - |
119 |
| - if nums[r] == target: |
120 |
| - Range[1] = r |
121 |
| - else: |
122 |
| - Range[1] = l |
123 |
| - |
124 |
| - return Range |
| 116 | + if nums[r] == target: result[1] = r |
| 117 | + elif nums[l] == target: result[1] = l |
| 118 | + else: raise ValueError() # 其实如果找到了第一个,一定能找到最后一个 |
| 119 | + |
| 120 | + return result |
125 | 121 | ```
|
126 | 122 |
|
127 |
| -- 使用模板 2 的解法 |
| 123 | +- 使用模板 2 的解法(暂略) |
128 | 124 |
|
129 | 125 | ```Python
|
130 | 126 | class Solution:
|
@@ -352,10 +348,10 @@ class Solution:
|
352 | 348 |
|
353 | 349 | 二分搜索核心四点要素(必背&理解)
|
354 | 350 |
|
355 |
| -- 1、初始化:start=0、end=len-1 |
356 |
| -- 2、循环退出条件:start + 1 < end |
357 |
| -- 3、比较中点和目标值:A[mid] ==、 <、> target |
358 |
| -- 4、判断最后两个元素是否符合:A[start]、A[end] ? target |
| 351 | +- 1、初始化:start=0、end=len-1 【固定】 |
| 352 | +- 2、循环退出条件:start + 1 < end 【模板1/3不同 |
| 353 | +- 3、比较中点和目标值:A[mid] ==、 <、> target 【模板1/3不同 |
| 354 | +- 4、判断最后两个元素是否符合:A[start]、A[end] ? target 【模板3独有 |
359 | 355 |
|
360 | 356 | ## 练习题
|
361 | 357 |
|
|
0 commit comments