074.搜索二维矩阵
作者:沉默王二
发布时间:2023-02-26T11:04:32.785+0800
本题解同时收录在星球专栏《二哥的 LeetCode 刷题笔记》中,专栏托管在语雀平台上(更方便你沉浸式阅读和做笔记,数学表达公式也能显示出来),访问地址和密码:https://t.zsxq.com/6iuzn6I
题意
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
难度
中等
示例
示例1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
示例2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
分析
一开始,我们会想到一个非常直观的算法——遍历整个二维数组,观察target是否出现过。
但是这样子的弊端很明显,如果target出现在整个二维数组的最后一个位置,那么所花费的时间代价是非常巨大的,而这个时间代价显然超出了我们的承受范围。
所以我们需要改进。
我们注意到该矩阵有两个特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
参照这两个性质,一个想法便油然而生了——我们能不能把这个二维数组拆成一条链呢?
也就是把题目转化为查找一个一维数组中有没有出现过target这个数。
这时候,我们的老朋友——“二分查找”,就能够派上用场了。
首先我们设置两个变量:lef 和rig。
分别让lef = 0,rig = n * m - 1。这时候,他们两个代表的就是转化后的一维数组的头跟尾。
接下来就按照二分查找的基本方法来操作了:取中值,判断中值与target的大小关系,如果比target大,则移动rig,如果小,则移动lef。而取得中值这一步,就是这个算法最为关键的地方。我们来观察下图:
这是经过我们对位置编码后的一个 3 * 4 的二维数组,例如一个数5,我们要确定它的行号和列号,只需要: ,,这时候我们就可以知道5的位置是matrix[1][1]了,类比这样的方式,我们就能够非常快速地取得中值。
class Solution {
int lef = 0,rig = matrix.length * matrix[0].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[mid / matrix[0].length][mid % matrix[0].length] == target) return true; if (matrix[mid / matrix[0].length][mid % matrix[0].length] < target) lef = mid + 1; else rig = mid - 1; } return false; }}
同样的,还有另外一种方法,我们先对第一列元素进行二分查找,确定target最可能存在的那一行,在该行中再进行一次二分查找,最终确定是否有target存在。
class Solution {
int lef = -1, rig = matrix.length - 1; while (lef < rig) { int mid = lef + (rig - lef + 1) / 2; if (matrix[mid][0] <= target) { lef = mid; } else { rig = mid - 1; } } int posX = lef; if (posX < 0) { System.out.println("SB"); //注意第一次查找就找不到比target更小的,则代表target不可能存在于matrix中 return false; } lef = 0; rig = matrix[posX].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[posX][mid] == target) { return true; } else if (matrix[posX][mid] > target) { rig = mid - 1; } else { lef = mid + 1; } } return false; }}
二种方法殊途同归,时间复杂度也是一样的,第一种方法的时间复杂度比较好直接计算,因为是一次二分查找,所以时间复杂度就是,第二种方法用了两次二分查找,第一次二分查找的时间复杂度是,第二次二分查找的时间复杂度是,所以总的时间复杂度是。
总结
本题的关键点在于找到位置转换的秘诀以及将整个二维数组拆分成链,最终才能用上我们的基本功——二分查找,所以说解题过程就是由灵感+扎实的基本功构成的。而扎实的基本功能让我们对灵感的捕捉更加敏感,不断锻炼自己的技能,我们也会不断进步。
力扣链接:https://leetcode.cn/problems/search-a-2d-matrix/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。
一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 1800 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!
本题解同时收录在星球专栏《二哥的 LeetCode 刷题笔记》中,专栏托管在语雀平台上(更方便你沉浸式阅读和做笔记,数学表达公式也能显示出来),访问地址和密码:https://t.zsxq.com/6iuzn6I
题意
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
难度
中等
示例
示例1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
示例2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
分析
一开始,我们会想到一个非常直观的算法——遍历整个二维数组,观察target是否出现过。
但是这样子的弊端很明显,如果target出现在整个二维数组的最后一个位置,那么所花费的时间代价是非常巨大的,而这个时间代价显然超出了我们的承受范围。
所以我们需要改进。
我们注意到该矩阵有两个特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
参照这两个性质,一个想法便油然而生了——我们能不能把这个二维数组拆成一条链呢?
也就是把题目转化为查找一个一维数组中有没有出现过target这个数。
这时候,我们的老朋友——“二分查找”,就能够派上用场了。
首先我们设置两个变量:lef 和rig。
分别让lef = 0,rig = n * m - 1。这时候,他们两个代表的就是转化后的一维数组的头跟尾。
接下来就按照二分查找的基本方法来操作了:取中值,判断中值与target的大小关系,如果比target大,则移动rig,如果小,则移动lef。而取得中值这一步,就是这个算法最为关键的地方。我们来观察下图:
这是经过我们对位置编码后的一个 3 * 4 的二维数组,例如一个数5,我们要确定它的行号和列号,只需要: ,,这时候我们就可以知道5的位置是matrix[1][1]了,类比这样的方式,我们就能够非常快速地取得中值。
class Solution {
int lef = 0,rig = matrix.length * matrix[0].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[mid / matrix[0].length][mid % matrix[0].length] == target) return true; if (matrix[mid / matrix[0].length][mid % matrix[0].length] < target) lef = mid + 1; else rig = mid - 1; } return false; }}
同样的,还有另外一种方法,我们先对第一列元素进行二分查找,确定target最可能存在的那一行,在该行中再进行一次二分查找,最终确定是否有target存在。
class Solution {
int lef = -1, rig = matrix.length - 1; while (lef < rig) { int mid = lef + (rig - lef + 1) / 2; if (matrix[mid][0] <= target) { lef = mid; } else { rig = mid - 1; } } int posX = lef; if (posX < 0) { System.out.println("SB"); //注意第一次查找就找不到比target更小的,则代表target不可能存在于matrix中 return false; } lef = 0; rig = matrix[posX].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[posX][mid] == target) { return true; } else if (matrix[posX][mid] > target) { rig = mid - 1; } else { lef = mid + 1; } } return false; }}
二种方法殊途同归,时间复杂度也是一样的,第一种方法的时间复杂度比较好直接计算,因为是一次二分查找,所以时间复杂度就是,第二种方法用了两次二分查找,第一次二分查找的时间复杂度是,第二次二分查找的时间复杂度是,所以总的时间复杂度是。
总结
本题的关键点在于找到位置转换的秘诀以及将整个二维数组拆分成链,最终才能用上我们的基本功——二分查找,所以说解题过程就是由灵感+扎实的基本功构成的。而扎实的基本功能让我们对灵感的捕捉更加敏感,不断锻炼自己的技能,我们也会不断进步。
力扣链接:https://leetcode.cn/problems/search-a-2d-matrix/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。
一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 1800 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!
本题解同时收录在星球专栏《二哥的 LeetCode 刷题笔记》中,专栏托管在语雀平台上(更方便你沉浸式阅读和做笔记,数学表达公式也能显示出来),访问地址和密码:https://t.zsxq.com/6iuzn6I
题意
编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
难度
中等
示例
示例1:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
示例2:
输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
分析
一开始,我们会想到一个非常直观的算法——遍历整个二维数组,观察target是否出现过。
但是这样子的弊端很明显,如果target出现在整个二维数组的最后一个位置,那么所花费的时间代价是非常巨大的,而这个时间代价显然超出了我们的承受范围。
所以我们需要改进。
我们注意到该矩阵有两个特性:
- 每行中的整数从左到右按升序排列。
- 每行的第一个整数大于前一行的最后一个整数。
参照这两个性质,一个想法便油然而生了——我们能不能把这个二维数组拆成一条链呢?
也就是把题目转化为查找一个一维数组中有没有出现过target这个数。
这时候,我们的老朋友——“二分查找”,就能够派上用场了。
首先我们设置两个变量:lef 和rig。
分别让lef = 0,rig = n * m - 1。这时候,他们两个代表的就是转化后的一维数组的头跟尾。
接下来就按照二分查找的基本方法来操作了:取中值,判断中值与target的大小关系,如果比target大,则移动rig,如果小,则移动lef。而取得中值这一步,就是这个算法最为关键的地方。我们来观察下图:
这是经过我们对位置编码后的一个 3 * 4 的二维数组,例如一个数5,我们要确定它的行号和列号,只需要: ,,这时候我们就可以知道5的位置是matrix[1][1]了,类比这样的方式,我们就能够非常快速地取得中值。
class Solution {
int lef = 0,rig = matrix.length * matrix[0].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[mid / matrix[0].length][mid % matrix[0].length] == target) return true; if (matrix[mid / matrix[0].length][mid % matrix[0].length] < target) lef = mid + 1; else rig = mid - 1; } return false; }}
同样的,还有另外一种方法,我们先对第一列元素进行二分查找,确定target最可能存在的那一行,在该行中再进行一次二分查找,最终确定是否有target存在。
class Solution {
int lef = -1, rig = matrix.length - 1; while (lef < rig) { int mid = lef + (rig - lef + 1) / 2; if (matrix[mid][0] <= target) { lef = mid; } else { rig = mid - 1; } } int posX = lef; if (posX < 0) { System.out.println("SB"); //注意第一次查找就找不到比target更小的,则代表target不可能存在于matrix中 return false; } lef = 0; rig = matrix[posX].length - 1; while (lef <= rig) { int mid = lef + (rig - lef) / 2; if (matrix[posX][mid] == target) { return true; } else if (matrix[posX][mid] > target) { rig = mid - 1; } else { lef = mid + 1; } } return false; }}
二种方法殊途同归,时间复杂度也是一样的,第一种方法的时间复杂度比较好直接计算,因为是一次二分查找,所以时间复杂度就是,第二种方法用了两次二分查找,第一次二分查找的时间复杂度是,第二次二分查找的时间复杂度是,所以总的时间复杂度是。
总结
本题的关键点在于找到位置转换的秘诀以及将整个二维数组拆分成链,最终才能用上我们的基本功——二分查找,所以说解题过程就是由灵感+扎实的基本功构成的。而扎实的基本功能让我们对灵感的捕捉更加敏感,不断锻炼自己的技能,我们也会不断进步。
力扣链接:https://leetcode.cn/problems/search-a-2d-matrix/
一步一个脚印
不积跬步无以至千里,不积小流无以成江海。LeetCode - 100天从算法小白到卷王正式启动了,我们计划周一到周五至少每天更新一篇,周六周日更新一篇,目标 300 道 LeetCode 经典题。
PDF 版本目前只针对**二哥编程星球 的球友开放,如果你也想一起打卡学习算法的话,戳链接 **加入我们吧。
一个人可以走得很快,但一群人才能走得更远。二哥编程星球 (目前已有 1800 多名球友加入)里面的每个球友都非常的友善,除了鼓励你,还会给你提出合理的建议,一起冲!
知识星球
扫码加入星球
查看更多优质内容
https://wx.zsxq.com/mweb/views/joingroup/join_group.html?group_id=15522885221412