判断数组为empty_剑指Offer[00]二维数组中的查找

529def049ab1d5f8dc4635e301eb3428.png

Description:

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

①外层遍历,内层二分:

最直观简单的暴力搜索

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        for(int i=0; i<row; i++)
        {
            int low = 0;
            int high = col-1;
            while(low <= high)
            {
                int mid = (low + high)/2;
                if(array[i][mid] == target)
                    return true;
                else if(array[i][mid] > target)
                    high = mid - 1;
                else
                    low = mid + 1;
            }
        }
        return false;
    }
};

②上述方法明显存在冗余,我们可以对外层遍历进行条件约束

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        for(int i=0; i<row; i++)
        {
            if(array[i].empty()) //列遍历操作的前提是数组非空
                return false;
            if(array[i][0] > target)// pruning
                return false;
            if(array[i][col-1] >= target) // pruning
            {
                int low = 0;
                int high = col-1;
                int mid = 0;
                while(low <= high)
                {
                    mid = (low + high) / 2; 
                    if(array[i][mid] == target)
                        return true;
                    else if(array[i][mid] > target)
                        high = mid - 1;
                    else
                        low = mid + 1;
                }
            }
        }
          return false;
    }
};

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty() || array[0].empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        for(int i=0; i<row; i++)
        {
            if(array[i][0] > target)
                return false;
            if(array[i][col-1] < target)
                continue;
            int low = 0;
            int high = col-1;
            int mid = 0;
            while(low <= high)
            {
                mid = (low + high) / 2; 
                if(array[i][mid] == target)
                    return true;
                else if(array[i][mid] > target)
                    high = mid - 1;
                else
                    low = mid + 1;
            }
    }
          return false;
    }
};

③递归+二维数组的二分查找:

首先定位到整个二维数组的中间位置,然后将其与 target 比较,若等于自然好可直接返回 true;若中间元素大于 target,则说明右下角的子矩阵一定是不存在target的(从上至下,从左至右递增排列),于是我们的搜索域划分缩减至左上角、左下角和右上角三个子矩阵,依次查找即可;中间元素小于 target 时同理,我们依次搜索右下角、左下角和右上角的子矩阵即可。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) 
    {
        if(array.empty() || array[0].empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        return r_Find(target, array, 0, row-1, 0, col-1);
    }
    
public:
    bool r_Find(int target, vector<vector<int> > array,int x_start, int x_end, int y_start, int y_end)
    {
        if(x_start == x_end && y_start == y_end)
            return (array[x_start][y_start] == target);
        int x_mid = (x_start + x_end) / 2;
        int y_mid = (y_start + y_end) / 2;
        if(array[x_mid][y_mid] == target)
            return true;
        if(x_start > x_end || y_start > y_end)//
            return false;
        else if(array[x_mid][y_mid] > target)
        {
            //依次搜索左上角矩阵、左下角矩阵和右上角矩阵
            if(r_Find(target, array, x_start, x_mid-1, y_start, y_mid-1))
                return true;
            if(r_Find(target, array, x_mid, x_end, y_start, y_mid-1))
                return true;
            if(r_Find(target, array, x_start, x_mid-1, y_mid+1, y_end))
                return true;
        }
        else
        {
            //依次搜索右下角矩阵、右下角矩阵和左上角矩阵
            if(r_Find(target, array, x_mid, x_end, y_mid+1, y_end))
                return true;
            if(r_Find(target, array, x_mid+1, x_end, y_start, y_mid))
                return true;
            if(r_Find(target, array, x_start, x_mid-1, y_mid+1, y_end))
                return true;
        }
        return false;
    }
};

④列、行删除进行查找:

利用左下角元素的特性(为该行最小值 && 该列最大值)来求解,小于 target 说明元素所在列均不符合要求,大于 target 则说明元素所在行过大,应该继续向上查找。

//左下角
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty() || array[0].empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        int x = row-1;
        int y = 0;
        while(x >= 0 && y < col)
        {
            if(array[x][y] == target)
                return true;
            else if (array[x][y] < target)
                ++y;
            else
                --x;
        }
        return false;
    }
};

//右上角同理
class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        if(array.empty() || array[0].empty())
            return false;
        int row = array.size();
        int col = array[0].size();
        int x = 0;
        int y = col - 1;
        while(x < row && y >= 0)
        {
            if(array[x][y] == target)
                return true;
            else if(array[x][y] > target)
                --y;
            else
                ++x;
        }
        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值