@@ -135,6 +135,95 @@ public boolean searchMatrix(int[][] matrix, int target) {
135
135
136
136
时间复杂度就是每个节点最多遍历一遍了,` O(m + n) ` 。
137
137
138
+ # 解法三
139
+
140
+ 参考 [ 这里] ( https://leetcode.com/problems/search-a-2d-matrix-ii/discuss/66147/*Java*-an-easy-to-understand-divide-and-conquer-method ) ,还有一种解法。
141
+
142
+ 我的理解的话,算是一种变形的二分法。
143
+
144
+ 二分法的思想就是,目标值和中点值进行比较,然后可以丢弃一半的元素。
145
+
146
+ 这道题的话是矩阵,如果我们找到矩阵的中心,然后和目标值比较看能不能丢弃一些元素。
147
+
148
+ ``` java
149
+ 如下图,中心位置是 9
150
+ [1 , 4 , 7 , 11 , 15 ],
151
+ [2 , 5 , 8 , 12 , 19 ],
152
+ [3 , 6 , / 9 / ,16 , 22 ],
153
+ [10 , 13 , 14 , 17 , 24 ],
154
+ [18 , 21 , 23 , 26 , 30 ]
155
+
156
+ 通过中心位置, 我们可以把原矩形分成四个矩形, 左上, 右上, 左下, 右下
157
+ [1 , 4 , 7 [11 , 15
158
+ 2 , 5 , 8 12 , 19
159
+ 3 , 6 , / 9 / ] 16 , 22 ]
160
+
161
+ [10 , 13 , 14 [17 , 24
162
+ [18 , 21 , 23 ] 26 , 30 ]
163
+
164
+ 如果 target = 10 ,
165
+ 此时中心值小于目标值,左上角矩形中所有的数都小于目标值,我们可以丢弃左上角的矩形,继续从剩下三个矩形中寻找
166
+
167
+ 如果 target = 5 ,
168
+ 此时中心值大于目标值,右下角矩形中所有的数都大于目标值,那么我们可以丢弃右下角的矩形,继续从剩下三个矩形中寻找
169
+ ```
170
+
171
+ 我们找到了丢弃元素的原则,可以写代码了。
172
+
173
+ 这里的话,矩形我们用左上角和右下角坐标的形式表示,下图是分割后矩形的坐标情况。
174
+
175
+ ![ ] ( https://windliang.oss-cn-beijing.aliyuncs.com/240_2.jpg )
176
+
177
+ 我们可以用递归的形式去写,递归出口的话,当矩阵中只有一个元素,直接判断当前元素是不是目标值即可。
178
+
179
+ 还有就是分割的时候可能越界,比如原矩阵只有一行,左下角和右下角的矩阵其实是不存在的,按照上边的坐标公式计算出来后,我们要判断一下是否越界。
180
+
181
+ ``` java
182
+ public boolean searchMatrix(int [][] matrix, int target) {
183
+ if (matrix. length == 0 || matrix[0 ]. length == 0 ) {
184
+ return false ;
185
+ }
186
+ return searchMatrixHelper(matrix, 0 , 0 , matrix[0 ]. length - 1 , matrix. length - 1 , matrix[0 ]. length - 1 , matrix. length - 1 , target);
187
+ }
188
+
189
+ private boolean searchMatrixHelper(int [][] matrix, int x1, int y1, int x2, int y2, int xMax, int yMax, int target) {
190
+ // 只需要判断左上角坐标即可
191
+ if (x1 > xMax || y1 > yMax) {
192
+ return false ;
193
+ }
194
+
195
+ // x 轴代表的是列,y 轴代表的是行
196
+ if (x1 == x2 && y1 == y2){
197
+ return matrix[y1][x1] == target;
198
+ }
199
+ int m1 = (x1 + x2) >>> 1 ;
200
+ int m2 = (y1 + y2) >>> 1 ;
201
+ if (matrix[m2][m1] == target) {
202
+ return true ;
203
+ }
204
+ if (matrix[m2][m1] < target) {
205
+ // 右上矩阵
206
+ return searchMatrixHelper(matrix, m1 + 1 , y1, x2, m2, x2, y2, target) ||
207
+ // 左下矩阵
208
+ searchMatrixHelper(matrix, x1, m2 + 1 , m1, y2, x2, y2, target) ||
209
+ // 右下矩阵
210
+ searchMatrixHelper(matrix, m1 + 1 , m2 + 1 , x2, y2, x2, y2, target);
211
+
212
+ } else {
213
+ // 右上矩阵
214
+ return searchMatrixHelper(matrix, m1 + 1 , y1, x2, m2, x2, y2, target) ||
215
+ // 左下矩阵
216
+ searchMatrixHelper(matrix, x1, m2 + 1 , m1, y2, x2, y2, target) ||
217
+ // 左上矩阵
218
+ searchMatrixHelper(matrix, x1, y1, m1, m2, x2, y2, target);
219
+ }
220
+ }
221
+ ```
222
+
138
223
# 总
139
224
140
- 看到有序数组第一反应就是二分了,也就是解法一。解法二的话,从右上角开始遍历的想法很妙。
225
+ 看到有序数组第一反应就是二分了,也就是解法一。
226
+
227
+ 解法二的话,从右上角开始遍历的想法很妙。
228
+
229
+ 解法三的话思想很简单,就是变形的二分法,每次抛弃一部分元素,但代码的话其实写出来不是很容易,相对于解法一和解法二来说是有些复杂度的。
0 commit comments