Skip to content

Commit 121d4a6

Browse files
committed
240
1 parent e822db6 commit 121d4a6

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,5 @@
219219
* [237. Delete Node in a Linked List](leetcode-237-Delete-Node-in-a-Linked-List.md)
220220
* [238. Product of Array Except Self](leetcode-238-Product-of-Array-Except-Self.md)
221221
* [239. Sliding Window Maximum](leetcode-239-Sliding-Window-Maximum.md)
222+
* [240. Search a 2D Matrix II](leetcode-240-Search-a-2D-MatrixII.md)
222223
* [更多](more.md)

leetcode-240-Search-a-2D-MatrixII.md

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# 题目描述(中等难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/240.jpg)
4+
5+
矩阵的每行从左到右是升序, 每列从上到下也是升序,在矩阵中查找某个数。
6+
7+
# 解法一
8+
9+
看到有序,第一反应就是二分查找。最直接的做法,一行一行的进行二分查找即可。
10+
11+
此外,结合有序的性质,一些情况可以提前结束。
12+
13+
比如某一行的第一个元素大于了 `target` ,当前行和后边的所有行都不用考虑了,直接返回 `false`
14+
15+
某一行的最后一个元素小于了 `target` ,当前行就不用考虑了,换下一行。
16+
17+
```java
18+
public boolean searchMatrix(int[][] matrix, int target) {
19+
if (matrix.length == 0 || matrix[0].length == 0) {
20+
return false;
21+
}
22+
for (int i = 0; i < matrix.length; i++) {
23+
if (matrix[i][0] > target) {
24+
break;
25+
}
26+
if(matrix[i][matrix[i].length - 1] < target){
27+
continue;
28+
}
29+
int col = binarySearch(matrix[i], target);
30+
if (col != -1) {
31+
return true;
32+
}
33+
}
34+
return false;
35+
}
36+
37+
//二分查找
38+
private int binarySearch(int[] nums, int target) {
39+
int start = 0;
40+
int end = nums.length - 1;
41+
while (start <= end) {
42+
int mid = (start + end) >>> 1;
43+
if (nums[mid] == target) {
44+
return mid;
45+
} else if (nums[mid] < target) {
46+
start = mid + 1;
47+
} else {
48+
end = mid - 1;
49+
}
50+
}
51+
return -1;
52+
}
53+
```
54+
55+
时间复杂度的话,如果是 `m``n` 列,就是 `O(mlog(n))`
56+
57+
# 解法二
58+
59+
参考 [这里](https://leetcode.com/problems/search-a-2d-matrix-ii/discuss/66140/My-concise-O(m%2Bn)-Java-solution),需要很敏锐的观察力了。
60+
61+
数组从左到右和从上到下都是升序的,如果从右上角出发开始遍历呢?
62+
63+
会发现每次都是向左数字会变小,向下数字会变大,有点和二分查找树相似。二分查找树的话,是向左数字变小,向右数字变大。
64+
65+
所以我们可以把 `target` 和当前值比较。
66+
67+
* 如果 `target` 的值大于当前值,那么就向下走。
68+
* 如果 `target` 的值小于当前值,那么就向左走。
69+
* 如果相等的话,直接返回 `true`
70+
71+
也可以换个角度思考。
72+
73+
如果 `target` 的值小于当前值,也就意味着当前值所在的列肯定不会存在 `target` 了,可以把当前列去掉,从新的右上角的值开始遍历。
74+
75+
同理,如果 `target` 的值大于当前值,也就意味着当前值所在的行肯定不会存在 `target` 了,可以把当前行去掉,从新的右上角的值开始遍历。
76+
77+
看下边的例子。
78+
79+
```java
80+
[1, 4, 7, 11, 15],
81+
[2, 5, 8, 12, 19],
82+
[3, 6, 9, 16, 22],
83+
[10, 13, 14, 17, 24],
84+
[18, 21, 23, 26, 30]
85+
86+
如果 target = 9,如果我们从 15 开始遍历, cur = 15
87+
88+
target < 15, 去掉当前列, cur = 11
89+
[1, 4, 7, 11],
90+
[2, 5, 8, 12],
91+
[3, 6, 9, 16],
92+
[10, 13, 14, 17],
93+
[18, 21, 23, 26]
94+
95+
target < 11, 去掉当前列, cur = 7
96+
[1, 4, 7],
97+
[2, 5, 8],
98+
[3, 6, 9],
99+
[10, 13, 14],
100+
[18, 21, 23]
101+
102+
target > 7, 去掉当前行, cur = 8
103+
[2, 5, 8],
104+
[3, 6, 9],
105+
[10, 13, 14],
106+
[18, 21, 23]
107+
108+
target > 8, 去掉当前行, cur = 9, 遍历结束
109+
[3, 6, 9],
110+
[10, 13, 14],
111+
[18, 21, 23]
112+
```
113+
114+
不管从哪种角度考虑,代码的话都是一样的。
115+
116+
```java
117+
public boolean searchMatrix(int[][] matrix, int target) {
118+
if (matrix.length == 0 || matrix[0].length == 0) {
119+
return false;
120+
}
121+
int row = 0;
122+
int col = matrix[0].length - 1;
123+
while (row < matrix.length && col >= 0) {
124+
if (target > matrix[row][col]) {
125+
row++;
126+
} else if (target < matrix[row][col]) {
127+
col--;
128+
} else {
129+
return true;
130+
}
131+
}
132+
return false;
133+
}
134+
```
135+
136+
时间复杂度就是每个节点最多遍历一遍了,`O(m + n)`
137+
138+
#
139+
140+
看到有序数组第一反应就是二分了,也就是解法一。解法二的话,从右上角开始遍历的想法很妙。

0 commit comments

Comments
 (0)