一起刷LeetCode——搜索二维矩阵(二分法)

65 阅读1分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

搜索二维矩阵

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性: 每行中的整数从左到右按升序排列。 每行的第一个整数大于前一行的最后一个整数。

来源:力扣(LeetCode) 链接:leetcode.cn/problems/se…

暴力破解

  • 二重循环遍历二维数组,遍历完就知道有没有这个目标值,但是时间复杂度比较高O(mn)

代码

var searchMatrix = function(matrix, target) {
    for(let i = 0; i < matrix.length; i++) {
        for(let j = 0; j < matrix[0].length; j++) {
            if(matrix[i][j] === target) return true
        }
    }
    return false
 };

二分查找

  • 每一行是有序的,分别对m行进行二分,时间复杂度为O(mlogn)

代码

var searchMatrix = function(matrix, target) {
    for(let i = 0; i < matrix.length; i++) {
        let start = 0, end = matrix[0].length - 1

        while(start <= end) {
            let mid = Math.floor((start + end) / 2)
            if(matrix[i][mid] === target) return true
            
            if(matrix[i][mid] > target) end = mid - 1
            else start = mid + 1
        }
    }
    return false
}

二分查找的优化

  • 除了每一行有序,每一行的第一个数字大于上一行的最后一个,可以把二维数组打平,把矩阵看成是一个一维数组,每一行首尾相连之后就是一个整体有序的数组,对整体用二叉查找,时间复杂度为O(logmn)

代码

var searchMatrix = function(matrix, target) {
  let start = 0, end = (matrix.length * matrix[0].length) - 1
    
    while(start <= end) {
        let mid = Math.floor((start + end) / 2)
        let midNum = 
            matrix[Math.floor(mid / matrix[0].length)][mid % matrix[0].length]
        
        if(midNum === target) return true    
        else if(midNum < target) start = mid + 1
        else end = mid - 1
    }
    return false
}

总结

  • 本题的难度是中等,推荐的解题方法是二分法
  • 这道题也是对二分法的一个扩展:就像上一篇说的,二分法的核心就是有序,寻找目标值,矩阵的每行是有序的,每行首尾相连之后,也是有序的,因此可以对矩阵整体进行二分,之后的解题难点可能是最中点位置的计算
  • 今天也是有收获的一天