【剑指offer】二维数组中的查找
创始人
2025-05-30 05:30:20
0

在这里插入图片描述

  • 👑专栏内容:剑指offer
  • ⛪个人主页:子夜的星的主页
  • 💕座右铭:前路未远,步履不停

目录

  • 一、题目描述
    • 1、题目
    • 2、示例
      • 示例Ⅰ
      • 示例Ⅱ
  • 二、题目分析
    • 1、暴力法
    • 2、二分法
    • 3、利用题目特性
  • 三、代码总结
    • 1、暴力法代码
    • 2、二分法代码
    • 3、利用特性


一、题目描述

1、题目

剑指offer:二维数组中的查找
在一个二维数组array中,每个一维数组的长度相同,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
在这里插入图片描述

2、示例

示例Ⅰ

输入:7,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:true
说明:存在7,返回true

示例Ⅱ

输入:3,[[1,2,8,9],[2,4,9,12],[4,7,10,13],[6,8,11,15]]
返回值:false
说明:不存在3,返回false

二、题目分析

1、暴力法

看见这道题的第一想法就是暴力法,通过两个循环,从二维数组的起始元素开始逐个遍历,如果当前元素等于目标值,则返回true,如果当前元素小于目标值,则继续遍历,如果遍历完所有元素还没有找到,就返回false
我们使用C++语言来实现此方法,在C++中,我们可以用vector嵌套vector的方式来表示二维数组。
empty() 判断数组是否为空
size()返回数组中元素的数量

class Solution {
public:bool Find(int target, vector > array) {if(array.empty())  //(1){ 	return false;}int rows = array.size(); //(2)int cols = array[0].size(); //(3)/*开始暴力遍历*/for(int i = 0;ifor(int j =0;jif(array[i][j]==target) return true;}}return false;}
};

(1)如果是空数组的话,直接返回false
(2)获取数组的行数
(3)获取数组的列数

暴力法的时间复杂度为O(mnmnmn),其中m和n分别是数组的行数和列数。

2、二分法

暴力法虽然能解决这个问题,但是时间复杂度比较高。
但是仔细想一下,暴力查找的过程,本质就是排除的过程,如果双循环暴力查找,本质是一次排除一个,效率过低,既然是查找,就可以利用二分查找法来缩减时间复杂度。
我们可以在每一行中进行二分查找,快速定位目标值所在的行或列,进寻找目标值所在的位置,减少查找的时间复杂度。

class Solution {
public:bool Find(int target, vector > array) {if (array.empty() || array[0].empty()) {return false;}for(int i=0;iint left = 0; //(1)int right = array[i].size()-1; //(2)while(left<=right) {int mid = (left + right )/2; // (3)if(target>array[i][mid])	left = mid + 1;	//(4)else if (target

(1)定义二分查找的左指针
(2)定义二分查找的右指针
(3)获取中间元素下表
(4)如果中间元素小于目标值,缩小左区间
(5)如果中间元素大于目标值,缩小右区间
(6)找到了返回true
(7)没用找到返回false

3、利用题目特性

利用二维数组由上到下,由左到右递增的规律。
我们可以从矩阵的右上角(或左下角)开始查找,如果目标值比当前位置的值小,则说明目标值可能在当前位置的左边;如果目标值比当前位置的值大,则说明目标值可能在当前位置的下面。这样每次查找都可以将查找范围缩小一行或一列,最多需要进行 m+nm+nm+n 次查找就可以找到目标值。
在这里插入图片描述

class Solution {public:bool Find(int target, vector > array) {// 判断矩阵是否为空if (array.empty() || array[0].empty()) {return false;}int i = 0; int j = array[0].size() - 1; //(1)while ( i < array.size() && j >= 0) {  if (target j--;  // (2)} else if (target > array[i][j]) {i++;  //(3)} else {return true;}}return false;}
};

(1)定义两个指针,分别指向第一行的第一个元素和第一行的最后一个元素。或者换句话说i指针控制的是行,j指针控制的是列,指针 i 指向第一行,指针 j 指向最后一列。
(2)如果当前位置的值大于目标值,说明当前列中的所有值都大于目标值,则将指针 j 左移一位。
(3)如果当前位置的值小于目标值,说明当前行中的所有值都小于目标值,则将指针 i 下移一位。

三、代码总结

1、暴力法代码

class Solution {
public:bool Find(int target, vector > array) {if(array.empty()){return false;}int rows = array.size();int cols = array[0].size();for(int i = 0;ifor(int j =0;jif(array[i][j]==target)return true;}}return false;}
};

2、二分法代码

class Solution {
public:bool Find(int target, vector > array) {for(int i=0;iint low = 0;int col = array[i].size()-1;while(low<=col){int mid = (low + col )/2;if(target>array[i][mid])low = mid + 1;else if (target

3、利用特性

class Solution {public:bool Find(int target, vector > array) {if (array.empty() || array[0].empty()) {return false;}int i = 0; int j = array[0].size() - 1; while ( i < array.size() && j >= 0) {  if (target j--;  } else if (target > array[i][j]) {i++;  } else {return true;}}return false;}
};

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...