欢迎来到王正伟的博客

返回顶部

面试题04:二维数组中的查找(C++)

题目地址:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/

题目描述

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

题目示例

现有矩阵 matrix 如下:

[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。

给定 target = 20,返回 false。

解题思路

思路1:暴力遍历查找,时间复杂度O(row*col),空间复杂度O(1),二维数组中的每个元素都被访问。

思路2:分析题目可以发现,数组元素之间存在一种特殊关系,即从左至右,从上至下都是递增的,因此我们选择以矩阵的右上角作为起点,并与target相比较,小于target则向下遍历,大于target则向左遍历,遍历完还没有则返回false。当然,我们也可以选择矩阵左下角为起点,与target相比较,大于target,则向上遍历,小于target,则向右遍历。时间复杂度O(row+col),空间复杂度O(1),因为访问到的下标的行最多增加row次,减少的列最多col次,因此,循环体最多执行row+col次。

思路3:二分搜索树思路。将矩阵右上角当作二叉搜索树的根节点,其左侧数字小于它,因此将左侧数字当做左子树,下侧数字当做右子树,满足二叉搜索树的”左子树小于根节点,根节点大于右子树“的条件,最后递归调用即可。时间复杂度O(nlogm),空间复杂度O(1)。

思路4:二分查找,这个方法可以是堆暴力遍历的一种优化,因为给定的数组是有序的,所以可以考虑二分查找。具体分析见文末参考文章。时间复杂度O(logn*logm),在行上查找一次的时间复杂度为O(logN),因为待查找的列的范围平均每次减少一半,故在行上查找logN次后列的范围就没有了,循环结束。同理,列上查找为O(log M)。

程序源码

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        //方法1:暴力法
        if(matrix.empty()) return false;
        int row = matrix.size(), col = matrix[0].size();
        for(int i = 0; i < row; i++)
        {
            for(int j = 0; j < col; j++)
            {
                if(matrix[i][j] == target) return true;
            }
        }
        return false;
        /*方法2:矩阵右上角开始
        if(matrix.empty()) return false;
        int row = 0, col = matrix[0].size() - 1;//右上角开始
        while(row < matrix.size() && col >= 0)
        {
            if(matrix[row][col] > target)
                col--;
            else if(matrix[row][col] < target)
                row++;
            else
                return true;
        }
        return false;
        */
        /*方法3:矩阵左下角开始
        if(matrix.empty()) return false;
        int row = matrix.size() - 1, col = 0;
        while(row >= 0 && col < matrix[row].size())
        {
            if(matrix[row][col] > target)
                row--;
            else if(matrix[row][col] < target)
                col++;
            else
                return true;
        }
        return false;
        */

    }
};

 思路3

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int rows = matrix.size();
        if(rows == 0) return false;
        int cols = matrix[0].size();
        if(cols == 0) return false;
        return binarySearch(matrix, target, 0, cols - 1, rows, cols);
    }
    bool binarySearch(vector<vector<int>> matrix, int target, int i, int j, int rows, int cols)
    {
        if(i >= rows || j < 0) return false; //越界
        int root = matrix[i][j]; //将右上角元素作为根节点
        if(root == target) return true;
        if(root > target) 
        {
            return binarySearch(matrix, target, i, j - 1, rows, cols); //遍历左子树 
        }
        else 
        {
            return binarySearch(matrix, target, i + 1, j, rows, cols); //遍历右子树
        }
    }
};

思路4:

class Solution {
public:
    bool findNumberIn2DArray(vector<vector<int>>& matrix, int target) {
        int rows = matrix.size();
        if(rows == 0) return false;
        int cols = matrix[0].size();
        if(cols == 0) return false;
        if(target < matrix[0][0] || target > matrix[rows - 1][cols - 1]) return false; //越界
        for(int i = 0; i < rows; ++i) //按行二分查找
        {
            int left = 0, right = cols - 1;
            while(left <= right)
            {
                int mid = left + (right - left) / 2;
                if(matrix[i][mid] == target) return true;
                if(matrix[i][mid] > target) 
                {
                    right = mid - 1;
                }
                else
                {
                    left = mid + 1;
                }
            }
        }
        return false;
    }
};

参考文章

https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/solution/cong-liang-ge-wei-du-jin-xing-er-fen-cha-zhao-by-w/

posted @ 2020-03-16 09:56  Mr.King~  阅读(1020)  评论(0编辑  收藏  举报