注:该篇文章会与我的个人博客同步更新。欢迎移步https://cqh-i.github.io/体验更好的阅读效果。
题目描述
编写一个高效的算法来判断 m ∗ n m*n m∗n矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 3
输出: true
示例 2:
输入:
matrix = [
[1, 3, 5, 7],
[10, 11, 16, 20],
[23, 30, 34, 50]
]
target = 13
输出: false
思路:
由于题目给出的矩阵具有两个特性, 特别是每行的第一个整数大于前一行的最后一个整数。那么我们将这个矩阵中的元素, 依次按行排到一行上,那么它就"变成"一个升序的"一维数组", 如示例1按行排如下:
[
[
1
,
3
,
5
,
7
]
,
[
10
,
11
,
16
,
20
]
,
[
23
,
30
,
34
,
50
]
]
[[1, 3, 5, 7],[10, 11, 16, 20],[23, 30, 34, 50]]
[[1,3,5,7],[10,11,16,20],[23,30,34,50]]. 如果我们将转化后的数组元素依次编号为0,1,2,3…,此时关键就在找出编号为x在原来矩阵的位置. 原来的矩阵位置也不难求, 设该矩阵每行有n个元素, 则在原来矩阵的下标为
(
⌊
x
n
⌋
,
x
%
n
)
(\lfloor\frac{x}{n}\rfloor, x \% n)
(⌊nx⌋,x%n)
然后采用二分查找算法就可以解决该问题了.
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0)
return false;
int num_column = matrix[0].length;
int num_row = matrix.length;
int low = 0;
int high = num_row * num_column - 1;
while (low <= high) {
int mid = low + (high - low) / 2;
if (matrix[mid / num_column][mid % num_column] == target)
return true;
if (matrix[mid / num_column][mid % num_column] > target) {
high = mid - 1;
} else {
low = mid + 1;
}
}
return false;
}
}