JZ4 二维数组中的查找

216 阅读2分钟

Day16 2023/01/23

题目链接

难度:简单

题目

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

[

[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]

给定 target = 7,返回 true。

给定 target = 3,返回 false。

数据范围:矩阵的长宽满足 0 ≤ n , m ≤ 500 , 矩阵中的值满足 0 ≤ val ≤ 10910^9
进阶:空间复杂度:O(1) ,时间复杂度: O(n+m)

示例1

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

示例2

输入:1,[[2]]
输出:false

思路


本题的进阶要求了时间复杂度: O(n+m),所以不能使用暴力解法,但是题目中要求的:每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序,所以可以使用 二分查找,时间复杂度也正好合适。大致的解题过程:逐行使用二分查找, 查找是否含有target

7C336804E8AC2B50043AB8C42C68418D.png

关键点


  • 对于二分查找不熟悉的朋友可以看这个:点击链接

算法实现


c++代码实现-二分查找

#include <iostream>
#include <vector>
using namespace std;

//按照题目要求输入数组数据
vector<vector<int>> createArray() {
    cout << "输入数组长宽,并输入数据:" << endl;
    int wh, val;
    cin >> wh; //二维数组长宽
    vector<vector<int>> arr(wh,  vector<int> (wh)); //创建一个长宽wh的二维数组
    for (int i = 0; i < wh; i++) { //外层控制行,内层控制列
        for (int j = 0; j < wh; j++) {
            cin >> val; 
            arr[i][j] = val; //赋值
        }
    }
    return arr; //返回二维数组
}

//二分查找目标元素(这里合法区间采用左闭右闭)
bool binarySearch(vector<int> arr, int target) {
    int left = 0, right = arr.size() - 1;
    while (left <= right) {
        int mid = left + ((right - left) >> 2);
        if (target > arr[mid]) left = mid + 1; //更新查找区间
        else if (target < arr[mid]) right = mid - 1;
        else return true; //成功找到返回
    }
    return false;
}

int main() {
    vector<vector<int>> arr = createArray(); //创建二维数组
    cout << "输入查找值:";
    int target; //查找值
    cin >> target;
    for (auto it : arr) { //it是复制的一份,无法影响真正的arr
        if(binarySearch(it, target)) cout << "成功找到";
    }
    return 0;
}
  • 时间复杂度 O(m+n)O(m + n) --- n为数组长度(一次二分查找循环n次),m为数组宽度(共调用m次二分查找)
  • 空间复杂度 O(1)O(1) ---数组为必要空间,无额外辅助空间

总结

  • 根据对复杂度要求的不同,解题方法也会有所限制。