这道题目要求我们在一个特殊的二维矩阵中高效地查找目标值。这个矩阵的特殊之处在于:
这种结构被称为"Young tableau",在计算机科学中有重要应用。理解这个特性是解题的关键,因为它决定了我们可以采用比普通矩阵更高效的搜索策略。
以题目给出的示例矩阵为例:
code复制[
[1, 4, 7, 11,15],
[2, 5, 8, 12,19],
[3, 6, 9, 16,22],
[10,13,14,17,24],
[18,21,23,26,30]
]
观察这个矩阵,我们可以发现几个重要特征:
这些特性意味着我们可以采用"排除法"来缩小搜索范围,而不是盲目地遍历整个矩阵。
最直观的解法是遍历矩阵中的每一个元素:
java复制public boolean bruteForceSearch(int[][] matrix, int target) {
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[0].length; j++) {
if (matrix[i][j] == target) {
return true;
}
}
}
return false;
}
注意:虽然这种方法简单直接,但在面对大型矩阵时效率极低。例如,对于1000×1000的矩阵,需要进行一百万次比较。
利用每行有序的特性,可以在每一行中使用二分查找:
java复制public boolean binarySearchPerRow(int[][] matrix, int target) {
for (int[] row : matrix) {
int left = 0, right = row.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (row[mid] == target) {
return true;
} else if (row[mid] < target) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return false;
}
优势:相比暴力解法有了显著提升,特别是当n较大时
不足:没有利用列有序的特性,仍有优化空间
从矩阵的右上角(或左下角)开始搜索:
以查找target=5为例:
java复制public boolean searchMatrix(int[][] matrix, int target) {
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) {
return false;
}
int row = 0;
int col = matrix[0].length - 1;
while (row < matrix.length && col >= 0) {
int current = matrix[row][col];
if (current == target) {
return true;
} else if (current > target) {
col--;
} else {
row++;
}
}
return false;
}
这是该问题的最优解法,充分利用了行列有序的特性
| 解法 | 时间复杂度 | 空间复杂度 | 是否利用有序性 |
|---|---|---|---|
| 暴力遍历 | O(m×n) | O(1) | 否 |
| 逐行二分 | O(m×log n) | O(1) | 行有序 |
| 右上角搜索 | O(m+n) | O(1) | 行列有序 |
虽然右上角搜索法已经是理论最优,但在实际实现中还可以:
这种搜索方法在以下场景有实际应用:
我在实际编码面试中发现,这道题很好地考察了候选人对二维数据结构的理解和对算法优化的思考能力。建议在准备面试时,不仅要掌握最优解法,还要理解各种解法的优劣比较,这样才能在面试中游刃有余。