力扣 74. 搜索二维矩阵---巧妙二分逐渐优化

74. 搜索二维矩阵

编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。

示例 1:

在这里插入图片描述

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 3
输出:true
示例 2:

在这里插入图片描述

输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,60]], target = 13
输出:false
 
提示:

m == matrix.length
n == matrix[i].length
1 <= m, n <= 100
-104 <= matrix[i][j], target <= 104

方法一:排序+二分

一种极其沙雕的做法,复杂度极高,但很容易想。

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
    
    
    int*res = (int*)malloc(sizeof(int)*10000);
    int k = 0;
    for(int i=0;i<matrixSize;i++)
    {
    
    
        for(int j=0;j<matrixColSize[0];j++)
        {
    
    
            res[k++] = matrix[i][j];
        }
    }
    int left = 0;
    int right = k-1;
    int mid;
    while(left<=right)
    {
    
    
        mid = left+(right-left)/2;
        if(res[mid]>target)
        {
    
    
            right = mid-1;
        }
        if(res[mid]<target)
        {
    
    
            left = mid+1;
        }
        if(res[mid]==target)
        {
    
    
            free(res);
            return 1;
        }
    }
    free(res);
    return 0;
}

方法二:n次二分

即每一行我们都进行一次二分查找,若能找到则跳出,找不到继续。

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
    
    
    for(int i=0;i<matrixSize;i++)
    {
    
    
        int left = 0;
        int right = matrixColSize[0]-1;
        int mid;
        while(left<=right)
        {
    
    
            mid = left+(right-left)/2;
            if(matrix[i][mid]>target)
            {
    
    
                right = mid-1;
            }
            if(matrix[i][mid]<target)
            {
    
    
                left = mid+1;
            }
            if(matrix[i][mid]==target)
            {
    
    
                return 1;
            }
        }
    }
    return 0;
}

方法三:两次二分

由于二维矩阵的特殊性,我们可以先对每一行的头部元素进行一个二分查找,查找到最贴近目标值且比它大的那一行时停止查找,对此行再次进行一个二分查找即可,因为目标值必定在其中。

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
    
    
    int left = 0;
    int right = matrixSize-1;
    int mid;
    while(left<right)
    {
    
    
        mid = left+(right-left+1)/2;//不多搞1则会卡住
        if(matrix[mid][0]>target)
        {
    
    
            right = mid-1;
        }
        if(matrix[mid][0]<=target)
        {
    
    
            left = mid;
        }
    }
    int temp = left;
    left = 0;
    right = matrixColSize[0]-1;
    while(left<=right)
    {
    
    
        mid = left+(right-left)/2;
        if(matrix[temp][mid]>target)
        {
    
    
            right = mid-1;
        }
        if(matrix[temp][mid]<target)
        {
    
    
            left = mid+1;
        }
        if(matrix[temp][mid]==target)
        {
    
    
            return 1;
        }
    }
    return 0;
}

方法四:一次二分

我们可以将有序二维转化为有序一维,继而对此一维数组进行一次二分即可。
即用降维后的mid除以每行所拥有的列数,即可得到其行数;
用mid除以每行所拥有的列数取余数,则得到其所在列数;

bool searchMatrix(int** matrix, int matrixSize, int* matrixColSize, int target){
    
    
    int left = 0;
    int m = matrixSize;
    int n = matrixColSize[0];
    int right = m*n-1;
    int mid;
    while(left<=right)
    {
    
    
        mid = left+(right-left)/2;
        if(matrix[mid/n][mid%n]>target)
        {
    
    
            right = mid-1;
        }
        if(matrix[mid/n][mid%n]<target)
        {
    
    
            left = mid+1;
        }
        if(matrix[mid/n][mid%n]==target)
        {
    
    
            return 1;
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiangguang_fight/article/details/115361370