当前位置: 首页 > article >正文

【Leetcode Top 100】240. 搜索二维矩阵 II

问题背景

编写一个高效的算法来搜索 m × n m \times n m×n矩阵 m a t r i x matrix matrix中的一个目标值 t a r g e t target target。该矩阵具有以下特性:

  • 每行的元素从左到右升序排列。
  • 每列的元素从上到下升序排列。

数据约束

  • m = = m a t r i x . l e n g t h m == matrix.length m==matrix.length
  • n = = m a t r i x [ i ] . l e n g t h n == matrix[i].length n==matrix[i].length
  • 1 ≤ n , m ≤ 300 1 \le n, m \le 300 1n,m300
  • − 1 0 9 < = m a t r i x [ i ] [ j ] < = 1 0 9 -10 ^ 9 <= matrix[i][j] <= 10 ^ 9 109<=matrix[i][j]<=109
  • 每行的所有元素从左到右升序排列
  • 每列的所有元素从上到下升序排列
  • − 1 0 9 ≤ t a r g e t ≤ 1 0 9 -10 ^ 9 \le target \le 10 ^ 9 109target109

解题过程

元素有序,首先想到二分法。然而本题中没有办法利用二分先确定待查找元素所在行或所在列,所以只能退而求其次遍历行或者列,再对另一个方向上用二分查找,这样做时间复杂度是 O ( m l o g n ) O(mlogn) O(mlogn) O ( n l o g m ) O(nlogm) O(nlogm)

如果从矩阵右上角出发,每次判断当前元素与目标值的大小关系,那么在没找到的情况下,每次都能排除掉一行或一列。事实上因为每次查找失败时,都能明确往哪个方向进行下一步搜索,所以这个做法相当于查找抽象的二叉搜索树,时间复杂度是 O ( m + n ) O(m + n) O(m+n)。理论上这样做在数据规模特别大的情况下会优于上一种思路,但是本题中数据量不是很大,两者区别不明显。

具体实现

按行或列二分查找

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int m = matrix.length, n = matrix[0].length;
        for(int i = 0; i < m; i++) {
            int left = 0, right = n - 1;
            while(left < right) {
                int mid = left + ((right - left) >>> 1);
                if(matrix[i][mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid;
                }
            }
            if(matrix[i][left] == target) {
                return true;
            }
        }
        return false;
    }
}

抽象二叉搜索树

class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        int i = 0, j = matrix[0].length - 1;
        while(i < matrix.length && 0 <= j) {
            if(matrix[i][j] == target) {
                return true;
            }
            if(matrix[i][j] < target) {
                i++;
            } else {
                j--;
            }
        }
        return false;
    }
}

http://www.kler.cn/a/409636.html

相关文章:

  • JS听到了替罪的回响
  • JavaScript的let、var、const
  • Debian/Ubuntu 、Fedora 、Arch Linux, 在Linux上,对文本文件进行多线程压缩 xz、pxz、zstd、7z、lrzip
  • 丹摩|丹摩智算平台深度评测
  • IEC61850读服务器目录命令——GetServerDirectory介绍
  • python中lxml 库之 etree 使用详解
  • 电脑无故提示提示“MSVCP140.dIl”文件丢失的原因以及六大解决方法!
  • Python入门(13)--并发编程
  • 银行卡OCR 识别 API 接口的影响因素分析
  • C++ —— 以真我之名 如飞花般绚丽 - 智能指针
  • python继承和反射
  • 今天你学C++了吗?——C++中的类与对象(第二集)
  • w~视觉~3D~合集3
  • 1、数据结构概述及顺序表(附:可以直接打印显示的源码)
  • 网络协议之UDP
  • 【Andriod ADB基本命令总结】
  • 【AI系统】谷歌 TPU v1-脉动阵列
  • npm命令报错
  • 【Java 学习】构造器、static静态变量、static静态方法、static构造器、
  • R语言处理JSON文件
  • 解决登录Google账号遇到手机上Google账号无法验证的问题
  • 一个高度可扩展的 Golang ORM 库【GORM】
  • git仓库:循环所有提交、查找有无指定文件名
  • Docker--通过Docker容器创建一个Web服务器
  • 使用 Volta 管理 Node.js 版本
  • Android 项目引入gradle Connect timed out