19
19
20
20
> 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
21
21
22
- ``` go
22
+ ``` c++
23
23
// 二分搜索最常用模板
24
- func search (nums [] int , target int ) int {
24
+ int search (vector< int > & nums, int target) {
25
25
// 1、初始化start、end
26
- start : = 0
27
- end := len ( nums) - 1
26
+ auto start = 0;
27
+ auto end = nums.size( ) - 1;
28
28
// 2、处理for循环
29
- for start+ 1 < end {
30
- mid : = start + (end- start)/ 2
29
+ while ( start + 1 < end) {
30
+ auto mid = start + (end - start) / 2;
31
31
// 3、比较a[ mid] 和target值
32
- if nums[mid] == target {
33
- end = mid
34
- } else if nums[mid] < target {
35
- start = mid
36
- } else if nums[mid] > target {
37
- end = mid
32
+ if ( nums[ mid] == target) {
33
+ return mid;
34
+ } else if ( nums[ mid] < target) {
35
+ start = mid;
36
+ } else {
37
+ end = mid;
38
38
}
39
39
}
40
40
// 4、最后剩下两个元素,手动判断
41
- if nums[start] == target {
42
- return start
41
+ if ( nums[ start] == target) {
42
+ return start;
43
43
}
44
- if nums[end] == target {
45
- return end
44
+ if ( nums[ end] == target) {
45
+ return end;
46
46
}
47
- return -1
47
+ return -1;
48
48
}
49
49
```
50
50
@@ -58,24 +58,24 @@ func search(nums []int, target int) int {
58
58
59
59
如果是最简单的二分搜索,不需要找第一个、最后一个位置、或者是没有重复元素,可以使用模板#1,代码更简洁
60
60
61
- ``` go
61
+ ```c++
62
62
// 无重复元素搜索时,更方便
63
- func search (nums [] int , target int ) int {
64
- start : = 0
65
- end := len ( nums) - 1
66
- for start <= end {
67
- mid : = start + (end- start)/ 2
68
- if nums[mid] == target {
69
- return mid
70
- } else if nums[mid] < target {
71
- start = mid+ 1
72
- } else if nums[mid] > target {
73
- end = mid- 1
63
+ int search(vector<int> & nums, int target) {
64
+ auto start = 0;
65
+ auto end = nums.size( ) - 1;
66
+ while ( start <= end) {
67
+ auto mid = start + (end - start) / 2;
68
+ if ( nums[mid] == target) {
69
+ return mid;
70
+ } else if ( nums[mid] < target) {
71
+ start = mid + 1;
72
+ } else {
73
+ end = mid - 1;
74
74
}
75
75
}
76
76
// 如果找不到,start 是第一个大于target的索引
77
77
// 如果在B+树结构里面二分搜索,可以return start
78
- // 这样可以继续向子节点搜索,如:node:= node.Children[start]
78
+ // 这样可以继续向子节点搜索,如:node = node.Children[start]
79
79
return -1
80
80
}
81
81
```
@@ -89,90 +89,80 @@ func search(nums []int, target int) int {
89
89
90
90
思路:核心点就是找第一个 target 的索引,和最后一个 target 的索引,所以用两次二分搜索分别找第一次和最后一次的位置
91
91
92
- ``` go
93
- func searchRange (A []int , target int ) []int {
94
- if len (A) == 0 {
95
- return []int {-1 , -1 }
92
+ ``` c++
93
+ // 两次搜索,一次相等时往左一次往右以找出左右边界
94
+ vector<int > searchRange (vector<int > &A, int target) {
95
+ vector<int > ret = {-1, -1};
96
+ if (A.empty()) {
97
+ return ret;
96
98
}
97
- result := make ([]int , 2 )
98
- start := 0
99
- end := len (A) - 1
100
- for start+1 < end {
101
- mid := start + (end-start)/2
102
- if A[mid] > target {
103
- end = mid
104
- } else if A[mid] < target {
105
- start = mid
99
+ int begin = 0;
100
+ int end = A.size();
101
+ while (begin + 1 < end) {
102
+ auto mid = begin + (end - begin) / 2;
103
+ if (A[ mid] < target) {
104
+ begin = mid;
106
105
} else {
107
- // 如果相等,应该继续向左找,就能找到第一个目标值的位置
108
- end = mid
106
+ end = mid;
109
107
}
110
108
}
111
- // 搜索左边的索引
112
- if A [start] == target {
113
- result[0 ] = start
114
- } else if A [end] == target {
115
- result[0 ] = end
109
+ if (A[ begin] == target) {
110
+ ret[ 0] = begin;
111
+ } else if (A[ end] == target) {
112
+ ret[ 0] = end;
116
113
} else {
117
- result[0 ] = -1
118
- result[1 ] = -1
119
- return result
114
+ return ret;
120
115
}
121
- start = 0
122
- end = len (A) - 1
123
- for start+1 < end {
124
- mid := start + (end-start)/2
125
- if A[mid] > target {
126
- end = mid
127
- } else if A[mid] < target {
128
- start = mid
116
+ begin = 0;
117
+ end = A.size();
118
+ while (begin + 1 < end) {
119
+ auto mid = begin + (end - begin) / 2;
120
+ if (A[ mid] <= target) {
121
+ begin = mid;
129
122
} else {
130
- // 如果相等,应该继续向右找,就能找到最后一个目标值的位置
131
- start = mid
123
+ end = mid;
132
124
}
133
125
}
134
- // 搜索右边的索引
135
- if A [end] == target {
136
- result[1 ] = end
137
- } else if A [start] == target {
138
- result[1 ] = start
126
+ if (A[ begin] == target) {
127
+ ret[ 1] = begin;
128
+ } else if (A[ end] == target) {
129
+ ret[ 1] = end;
139
130
} else {
140
- result[0 ] = -1
141
- result[1 ] = -1
142
- return result
131
+ return ret;
143
132
}
144
- return result
133
+ return ret;
145
134
}
146
135
```
147
136
148
137
### [search-insert-position](https://leetcode-cn.com/problems/search-insert-position/)
149
138
150
139
> 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
151
140
152
- ``` go
153
- func searchInsert (nums []int , target int ) int {
154
- // 思路:找到第一个 >= target 的元素位置
155
- start := 0
156
- end := len (nums) - 1
157
- for start+1 < end {
158
- mid := start + (end-start)/2
159
- if nums[mid] == target {
160
- // 标记开始位置
161
- start = mid
162
- } else if nums[mid] > target {
163
- end = mid
141
+ ```c++
142
+ int searchInsert(vector<int>& nums, int target) {
143
+ if (nums.empty()) {
144
+ return 0;
145
+ }
146
+
147
+ int begin = 0;
148
+ int end = nums.size() -1;
149
+ while (begin + 1 < end) {
150
+ auto mid = begin + (end - begin) / 2;
151
+ if (nums[mid] == target) {
152
+ return mid;
153
+ } else if (nums[mid] < target) {
154
+ begin = mid;
164
155
} else {
165
- start = mid
156
+ end = mid;
166
157
}
167
158
}
168
- if nums[start] >= target {
169
- return start
170
- } else if nums[end] >= target {
171
- return end
172
- } else if nums[end] < target { // 目标值比所有值都大
173
- return end + 1
174
- }
175
- return 0
159
+ if (nums[begin] >= target) {
160
+ return begin;
161
+ } else if (nums[end] >= target) {
162
+ return end;
163
+ } else {
164
+ return end + 1;
165
+ }
176
166
}
177
167
```
178
168
@@ -183,32 +173,46 @@ func searchInsert(nums []int, target int) int {
183
173
> - 每行中的整数从左到右按升序排列。
184
174
> - 每行的第一个整数大于前一行的最后一个整数。
185
175
186
- ``` go
187
- func searchMatrix (matrix [][]int , target int ) bool {
188
- // 思路:将2纬数组转为1维数组 进行二分搜索
189
- if len (matrix) == 0 || len (matrix[0 ]) == 0 {
190
- return false
176
+ ``` c++
177
+ bool searchMatrix (vector<vector<int >>& matrix, int target) {
178
+ if (matrix.empty() || matrix[ 0] .empty()) {
179
+ return false;
191
180
}
192
- row := len (matrix)
193
- col := len (matrix[0 ])
194
- start := 0
195
- end := row*col - 1
196
- for start+1 < end {
197
- mid := start + (end-start)/2
198
- // 获取2纬数组对应值
199
- val := matrix[mid/col][mid%col]
200
- if val > target {
201
- end = mid
202
- } else if val < target {
203
- start = mid
181
+
182
+ int begin = 0;
183
+ int end = matrix.size() - 1;
184
+ while (begin + 1 < end) {
185
+ auto mid = begin + (end - begin) / 2;
186
+ const auto &val = matrix[mid][0];
187
+ if (val == target) {
188
+ return true;
189
+ } else if (val < target) {
190
+ begin = mid;
204
191
} else {
205
- return true
192
+ end = mid;
206
193
}
207
194
}
208
- if matrix[start/col][start%col] == target || matrix[end/col][end%col] == target{
209
- return true
195
+
196
+ if (matrix[begin][0] == target || matrix[end][0] == target) {
197
+ return true;
210
198
}
211
- return false
199
+ if (matrix[begin][0] > target || matrix[end][matrix[end].size()- 1] < target) {
200
+ return false;
201
+ }
202
+ const auto &row = matrix[end][0] < target ? matrix[end] : matrix[begin];
203
+ begin = 0;
204
+ end = row.size() - 1;
205
+ while (begin + 1 < end) {
206
+ auto mid = begin + (end - begin) / 2;
207
+ if (row[mid] == target) {
208
+ return true;
209
+ } else if (row[mid] < target) {
210
+ begin = mid;
211
+ } else {
212
+ end = mid;
213
+ }
214
+ }
215
+ return row[begin] == target || row[end] == target;
212
216
}
213
217
```
214
218
@@ -217,23 +221,19 @@ func searchMatrix(matrix [][]int, target int) bool {
217
221
> 假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
218
222
> 你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
219
223
220
- ``` go
221
- func firstBadVersion (n int ) int {
222
- // 思路:二分搜索
223
- start := 0
224
- end := n
225
- for start+1 < end {
226
- mid := start + (end - start)/2
227
- if isBadVersion (mid) {
228
- end = mid
229
- } else if isBadVersion (mid) == false {
230
- start = mid
224
+ ```c++
225
+ int firstBadVersion(int n) {
226
+ int begin = 1;
227
+ int end = n;
228
+ while (begin + 1 < end) {
229
+ auto mid = begin + (end - begin) / 2;
230
+ if (isBadVersion(mid)) {
231
+ end = mid;
232
+ } else {
233
+ begin = mid;
231
234
}
232
235
}
233
- if isBadVersion (start) {
234
- return start
235
- }
236
- return end
236
+ return isBadVersion(begin) ? begin : end;
237
237
}
238
238
```
239
239
@@ -242,28 +242,20 @@ func firstBadVersion(n int) int {
242
242
> 假设按照升序排序的数组在预先未知的某个点上进行了旋转( 例如,数组 [ 0,1,2,4,5,6,7] 可能变为 [ 4,5,6,7,0,1,2] )。
243
243
> 请找出其中最小的元素。
244
244
245
- ``` go
246
- func findMin (nums []int ) int {
247
- // 思路:/ / 最后一个值作为target,然后往左移动,最后比较start、end的值
248
- if len (nums) == 0 {
249
- return -1
250
- }
251
- start := 0
252
- end := len (nums) - 1
253
-
254
- for start+1 < end {
255
- mid := start + (end-start)/2
256
- // 最后一个元素值为target
257
- if nums[mid] <= nums[end] {
258
- end = mid
245
+ ``` c++
246
+ int findMin (vector<int >& nums) {
247
+ // 最后一个值作为target,以确定是否旋转
248
+ int begin = 0;
249
+ int end = nums.size() - 1;
250
+ while (begin + 1 < end) {
251
+ auto mid = begin + (end - begin) / 2;
252
+ if (nums[ mid] <= nums[ end] ) {
253
+ end = mid;
259
254
} else {
260
- start = mid
255
+ begin = mid;
261
256
}
262
257
}
263
- if nums[start] > nums[end] {
264
- return nums[end]
265
- }
266
- return nums[start]
258
+ return nums[ begin] > nums[ end] ? nums[ end] : nums[ begin] ;
267
259
}
268
260
```
269
261
@@ -273,7 +265,7 @@ func findMin(nums []int) int {
273
265
> ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
274
266
> 请找出其中最小的元素。(包含重复元素)
275
267
276
- ``` go
268
+ ```c++
277
269
func findMin(nums []int) int {
278
270
// 思路:跳过重复元素,mid值和end值比较,分为两种情况进行处理
279
271
if len(nums) == 0 {
0 commit comments