【九章斩题录】C/C++:二维数组中的查找(JZ4)

这篇具有很好参考价值的文章主要介绍了【九章斩题录】C/C++:二维数组中的查找(JZ4)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  【九章斩题录】C/C++:二维数组中的查找(JZ4)精品题解 👉 《九章刷题录》

📜 目录:

「 法一 」暴力美学

「 法二 」十字分割法

「 法三 」逐行二分


JZ4 - 二维数组中的查找

📚 题目描述:在一个二维数组 array 中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

比如下列二维数组 ,给定 target = 3,则返回 true给定 target = 7,则返回 false

int a[3][4] = {{1, 2, 3, 4}, {2, 3, 4, 5}, {3, 4, 5, 6}};  // C
  • 数据范围:矩阵的长宽满足  , 矩阵中的值满足 
  • 进阶:时间复杂度 【九章斩题录】C/C++:二维数组中的查找(JZ4),空间复杂度 

💭 示例:I/O

输入: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   

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

✅ 模板:C语言

/**
 * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
 *
 * 
 * @param target int整型 
 * @param array int整型二维数组 
 * @param arrayRowLen int array数组行数
 * @param arrayColLen int* array数组列数
 * @return bool布尔型
 */
bool Find(int target, int** array, int arrayRowLen, int* arrayColLen ) {
    // write code here
}

✅ 模板:C++

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
    }
};

「 法一 」暴力美学

" 别和我说什么二分线性算法,老夫敲代码就是一把梭,直接 for 暴力! "

💡 思路:既然是要找数组中是否存在某个数字,直接逐行逐列遍历搜索即可。对于二维数组的遍历,需要用两层循环,因此时间复杂度为 ,空间复杂度为 。

💬 代码演示:C语言

#include <stdbool.h>
bool Find(int target, int** array, int arrayRowLen, int* arrayColLen) {
    for (int i = 0; i < arrayRowLen; i++) {        // 遍历行
        for (int j = 0; j < *arrayColLen; j++) {   // 遍历列
            if (array[i][j] == target) {
                return true;   // 找到了
            }
        }
    }
    return false;    // 没找到
}

 我们定义  搜索二维数组,如果找到了目标值则返回 true,如果搜索完仍未找到我们根据题意返回 -1 即可。


「 法二 」十字分割法

" 既有规律可循,一次排除一批,岂不美哉?"

💡 思路:题中描述的数组是存在规律的:"在一个二维数组 array 中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。" 这就意味着矩阵内部的行列都是有序,数组右上角的值在这一行中是最大的,而在这一列中是最小的。,每次判断都能剔除一整行或一整列。

【九章斩题录】C/C++:二维数组中的查找(JZ4)

我们思考一个问题 —— "一次排除一个和一次排除一批",谁的效率更高?当然是后者效率更高!如果按照这个本质,我们在套上我们想到的 「法1」,其本质就是一次排除一个,效率自然也就不能再高了。我们观察这样的数组,我们可以通过比较目标值,和数组中右上角的值(或左下角的值),因为右上角的值是这一行中最大的,是这一列中最小的。

对我们而言,我们可以 直接拿着目标值,和当前矩阵的右上角的值进行比较。 如果当前值比右上角的值小,说明当前你要查找的值是绝对不会出现在这一列的,就可以把这一列整体排除。

现在我们就做到一行排除一行或者一列了。此时我们就需要考虑临界条件的问题,我们要关注什么时候结束,找到了,如果没找到,一定是一个行或者列出现了越界的条件,导致程序退出。排除时,行不断加,列不断减,因此临界条件为:行 (row) 不能增到 arrayRowLen,列 (col) 不能缩到比 0 小。

📚 介绍:上面我们介绍的这种方法,称之为 十字分割法 (Cross-Sectional Search),是在有序二维数组中查找目标元素的高效算法,当然前提是有序!它利用了有序数组的特性,通过逐步缩小搜索范围来快速确定目标元素的位置。"十字" 也很形象的表现出排除 "每次判断都能剔除一整行或一整列" 的特点。通过不断缩小搜索范围,十字分割法可以快速确定目标元素的位置,从而提高查找的效率。十字分割法的基本步骤如下:

Step1:选择一个起始点,通常是数组的右上角或左下角(个人习惯于右上角)

Step2:将起始点的值与目标元素进行比较。

Step3:如果起始点的值等于目标元素,找到目标元素,搜索结束。

Step4:如果起始点的值大于目标元素,目标元素可能在当前元素的左边或上方,将搜索范围缩小到当前元素的左边区域或上方区域。

Step5:如果起始点的值小于目标元素,目标元素可能在当前元素的右边或下方,将搜索范围缩小到当前元素的右边区域或下方区域。

* 重复步骤 2~5,直到找到目标元素,或达到临界条件(数组不能越界)!

该方法的时间复杂度为 【九章斩题录】C/C++:二维数组中的查找(JZ4) ,其中  为二维数组的行数, 为二维数组的列数。

💬 代码演示:C语言

bool Find(int target, int** array, int arrayRowLen, int* arrayColLen ) {
    int row = 0;                // 当前行
    int col = arrayRowLen - 1;  // 当前列

    while (row < arrayRowLen && col >= 0) {
        // array[row][col] 必定是当前行最大的,当前列最小的
        if (target < array[row][col]) {   // 如果目标值小于右上角
            col--;   // 不可能出现在该列,排除
        }
        else if (target > array[row][col]) {  // 如果目标值大于右上角
            row++;  // 不可能出现在该行,排除
        }
        else {
            return true;   // 找到了
        }
    }
    return false;    // 没找到
}

我们定义 row 和 col,初始化使 array[row][col] 能指向右上角,此时 array[row][col] 必然是当前行最大的,当前列最小的。主要判断目标值和 array[row][col] 的大小,如果比它小,那肯定不会出现在该列,因为垂直往下只会有更大的,所以肯定不在该列,直接 col-- 排除该列。如果比它大。那肯定不会出现在该行,因为横向只有比它还要小的,所以肯定不在该行,直接 row++ 排除该行,走到下一行。如此一来我们搜索的范围越来越小,最后如果有满足 target == array[row][col] 条件的情况就可以返回 true 了,数组都缩没了还没找到那自然是根本不存在目标值,循环外返回 false 即可。至于这里的循环边界的控制,是决定循环什么时候结束的关键!row 作为行,是肯定要比行长度 arrayRowLen 小的,如果 row++ 到 arrayRowLen 这个边界了,就会越界。同样,col-- 到 0 下标时如果在继续减也会越界,所以这里循环控制把控好就行。

时间复杂度为 【九章斩题录】C/C++:二维数组中的查找(JZ4)(R 表示行 C 表示列),空间复杂度为 。


「 法三 」逐行二分

" 逐行二分搜之…… "

💡 思路:我们可以对数组的每行进行二分查找!手写一个 BinarySearch 函数,然后只需要逐行传递给该函数即可。对数组地每一行使用二分,其时间复杂度为 ,空间复杂度为 。

【九章斩题录】C/C++:二维数组中的查找(JZ4)

💬 代码演示:C语言

#include <stdbool.h>
int binary_search(int* arr, int sz, int k) {
    int left = 0;
    int right = sz - 1;
    int mid = 0;

    while (left <= right) {
        mid = (left + right) / 2;
        if (arr[mid] < k) {
            left = mid + 1;
        } 
        else if (arr[mid] > k) {
            right = mid - 1;
        } 
        else {
            return mid;  // 找到了
        }
    }

    return -1;  // 没找到
}

bool Find(int target, int** array, int arrayRowLen, int* arrayColLen ) {
    int ret = 0;   // 用于接收返回值

    // 遍历行,将行依次传给 binary_search 函数
    for (int i = 0; i < arrayRowLen; i++) {
        ret = binary_search(array[i], *arrayColLen, target);
        if (ret != -1) {
            return true;   // 找到了
        }
    }
    return false;
}

我们手动实现好 BinrarySearch 函数后,我们只需要写一个 for 循环,把行依次传入该数组。会先把第一行数组传给该函数,如果找到了就结束了,没找到就继续把下一行传给该函数以此类推……最后如果没有找到根据题意返回 -1 即可。

【九章斩题录】C/C++:二维数组中的查找(JZ4)

📌 [ 笔者 ]   王亦优
📃 [ 更新 ]   2023.5.24
❌ [ 勘误 ]   /* 暂无 */
📜 [ 声明 ]   由于作者水平有限,本文有错误和不准确之处在所难免,
              本人也很想知道这些错误,恳望读者批评指正!

📜 参考资料 

C++reference[EB/OL]. []. http://www.cplusplus.com/reference/.

Microsoft. MSDN(Microsoft Developer Network)[EB/OL]. []. .

百度百科[EB/OL]. []. https://baike.baidu.com/.

牛客网. 剑指offer 题解 [EB/OL]. []. https://www.nowcoder.com/exam/oj/ta?tpId=13.文章来源地址https://www.toymoban.com/news/detail-468019.html

到了这里,关于【九章斩题录】C/C++:二维数组中的查找(JZ4)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 剑指offer -- 二维数组中的查找

    二维数组中的查找_牛客题霸_牛客网 (nowcoder.com) 暴力查找法: 是一种简单直接的解决方法,可以用于在二维数组中查找目标值。该方法的思路是遍历数组的每个元素,逐个与目标值进行比较。 具体步骤如下: 从数组的第一行第一列开始,逐行逐列地遍历数组的每个元素。 对

    2024年02月06日
    浏览(75)
  • 剑指offer中算法:二维数组中的查找

    在一个 n * m 的二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个高效的函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。 示例 现有矩阵 matrix 如下: { {1, 4, 7}, {2, 5, 8,}, {3, 6, 9} } 给定 target = 9,

    2024年02月12日
    浏览(33)
  • 剑指29.顺时针打印矩阵 31 栈的压入,弹出序列 03 数组中的重复数字 53缺失的数字 04二维数组中的查找

    回字形 思路:pushed数组里遍历进栈,遍历时候,先进栈,再判断栈顶是否和poped序列的当前指向的是否一样,一样就pop,直到不一样为止,然后继续遍历进栈。然后再判断栈里面剩余的和poped序列指向的一不一样,一样,就把栈里面的pop,直到栈为空,只要有一个不一样,就

    2024年02月16日
    浏览(31)
  • VBA 二维数组查找并定位数据

    数据源:   将这个二维数组导入内存后,存储到一个二维数组里,查找其中一个数组成员,返回其在表格中的地址. 如找44,返回M20

    2024年02月16日
    浏览(29)
  • C语言 查找二维数组的鞍点

    出具有m行n列二维数组的“鞍点”,即该位置上的元素在该行上最大,在该列上最小,其中1=m,n=10。同一行和同一列没有相同的数。要求:     1)输入m和n,输入格式m*n;     2)输入m行每行n个整数。     3)查找鞍点。     4)如果找到鞍点,则输出该元素所在行、列和值,

    2024年02月05日
    浏览(49)
  • LeetCode-74. 搜索二维矩阵【数组 二分查找 矩阵】

    给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回 false 。 示例 1: 输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]],

    2024年04月14日
    浏览(34)
  • C语言例题(二维数组)【转置矩阵】【成绩登记】【斐波那契】【简单矩阵查找】【螺旋数阵】【一维数组转二维数组】

    例一:转置矩阵 程序: 输出:通过b[j][i] = a[i][j];这一步实现了转置 进阶:用6个1~20内的随机数按行的顺序生成一个a[2][3]的矩阵,并输出它的转置矩阵 输出: 例2.登记某班三人的数学、英语两门课程的成绩。 分析:此类问题可以通过使用3个一维数组来解决,也可以通过使用

    2024年02月03日
    浏览(34)
  • JavaSE进阶 | 二维数组的定义和使用、查找和排序算法

    目录 🥅二维数组 ❤️二维数组的遍历 ❤️动态初始化二维数组 🥅数组知识点总结 🥅习题练习 ❤️用数组模拟栈 ❤️模拟酒店的订房退房功能 ❤️杨辉三角 ❤️把数据存入数组,保证值各不相同 ❤️数组元素的赋值与数组复制 ❤️数组元素的反转 ❤️数组的扩容与缩

    2024年02月14日
    浏览(31)
  • 详解Leetcode中关于malloc模拟开辟二维数组问题,涉及二维数组的题目所给函数中的各个参数的解读

    最近博主一直再刷Leetcode上有关c语言的题目,有些题目第一步就将我卡死了。为什么呢?因为题目中所给的函数里的参数的具体含义我既然都不知道是什么意思。当然在请教了一些大佬后我也顺利解决了,不然也不会有人和你们分享了,哈哈哈~ 我就已一个典型的题目来介绍

    2024年02月08日
    浏览(30)
  • (78)删除有序数组中的重复项(79)排序矩阵查找

    水晶帘动微风起,满架蔷薇一院香。 —高骈- 题目链接:删除有序数组中的重复项 给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个

    2024年04月17日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包