一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情。
本周继续顺着前几天的思路刷二分法的题目,先把简单和中等的全部做完,再去挑战困难的。
题目描述
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
示例 1:
输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出: true
示例 2:
输入: matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出: false
思路
这题相对于最基础的二分搜索,有一个小变化,就是数组从一维变成了二维。不过根据这个矩阵的特点,我们可以把这个二维的矩阵转化成为一个一维数组。
对于示例1中的矩阵,我们把数据打平成一个一维数组的话,应该是这样的顺序:num[0][0]、num[0][1]、num[0][2]、num[0][3]、num[1][0]、num[1][1]、num[1][2]、num[1][3]、num[2][0]、num[2][1]、num[2][2]、num[2][3];不难发现,其实这个下标的顺序,就是对应一个4进制的数,转为10进制,就是我们熟悉的0~11。推广到m*n的矩阵,其实可以把下标看成n进制的数据,就是使用一个数来标示2维的2个下标。同样的,如果有一个10进制的数值,我们也可以转换出来2维的下标。通过这一次转换,我们可以把原始的二维矩阵转换成一维的数组,就是我们常见的二分查找问题了。
Java版本代码
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
int m = matrix.length;
int n = matrix[0].length;
int left = 0, right = m*n-1;
while (left <= right) {
int mid = left + (right-left)/2;
int x = mid/n;
int y = mid%n;
if (target == matrix[x][y]) {
return true;
} else if (target < matrix[x][y]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
return false;
}
}