面試題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/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM