菜鸡每日一题系列打卡74天
每天一道算法题目
小伙伴们一起留言打卡
坚持就是胜利,我们一起努力!
题目描述(引自LeetCode)
编写一个高效的算法来判断m x 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
题目分析
这明显是一道二分法的题目。我们可以采用两种思路来实现:一种是先对行进行二分,找到target可能在的行,然后再对列进行二分,判断target是否存在。另一种是对所有的数当作一维有序数组进行二分,然后映射到二维数组的对应坐标中。
Talk is cheap,菜鸡将采用上述两种方法进行实现。话不多说,上代码!
代码实现
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
// 特殊情况处理
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
int rowStart = 0, rowEnd = matrix.length - 1, rowMid = 0;
int colStart = 0, colEnd = matrix[0].length - 1;
// 二分法寻找行
while (rowStart <= rowEnd) {
rowMid = rowStart + ((rowEnd - rowStart) >> 1);
if (matrix[rowMid][0] == target) return true;
else if (matrix[rowMid][0] > target) rowEnd = rowMid - 1;
else if (matrix[rowMid][colEnd] < target) rowStart = rowMid + 1;
else break;
}
// 二分法寻找列
while (colStart <= colEnd) {
int colMid = colStart + ((colEnd - colStart) >> 1);
if (matrix[rowMid][colMid] == target) return true;
else if (matrix[rowMid][colMid] > target) colEnd = colMid - 1;
else colStart = colMid + 1;
}
return false;
}
}
class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
// 特殊情况处理
if (matrix == null || matrix.length == 0 || matrix[0].length == 0) return false;
int m = matrix.length;
int n = matrix[0].length;
// 二分法
int start = 0, end = m * n - 1;
while (start <= end) {
// 按照一维数组来计算中间坐标
int mid = start + ((end - start) >> 1);
// 定位中间坐标所在行
int row = mid / n;
// 定位中间坐标所在列
int column = mid % n;
// 比较判断
if (matrix[row][column] == target) return true;
else if (matrix[row][column] > target) end = mid - 1;
else start = mid + 1;
}
return false;
}
}
代码分析
对代码进行分析,第一种实现方式,对行和列分别进行二分,时间复杂度为O(max(logm, logn)),空间复杂度为O(1);第二种实现方式,对所有数字进行二分,然后映射到具体的二维数组坐标,时间复杂度为O(log(mn)),空间复杂度为O(1)。
乍一看,觉得第一种实现方式的时间复杂度好像更低一些,其实只要稍加分析,对于第二种实现方式,log(mn) = logm + logn,就会发现,这只是个数学游戏而已,两种实现方式的时间复杂度并无本质区别。
执行结果
对行和列分别进行二分的执行结果
对所有数字进行二分然后进行下标映射的执行结果
学习 | 工作 | 分享
????长按关注“有理想的菜鸡”
只有你想不到,没有你学不到