剑指offer--二维数组查找

本文介绍了一种在特殊排序的二维数组中查找特定整数的方法,包括三种不同的算法实现:通过模拟二叉判定树进行查找、逐行使用二分查找以及采用矩阵二分法。这些方法不仅高效而且适用于不同场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

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

1、二分查找的过程中,会产生一棵二叉判定树,二叉判定树的特点就是,左子树小于根节点,右子树大于根节点。利用这个性质,我们可以将二维数组模拟成一个二叉判定树,此时就需要找出根节点,使得左子树小于根节点,右子树大于根节点,并且它的孩子节点也符合这种特性。

利用二维数组由上到下,由左到右递增的规律,那么选取右上角或者左下角的元素a[row][col]与target进行比较,
当target小于元素a[row][col]时,那么target必定在元素a所在行的左边,即col--;
当target大于元素a[row][col]时,那么target必定在元素a所在列的下边,即row++;

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int row,col,m,n;
        m=array.size();  //求数组的行数
        n=array[0].size(); //求数组的列数 
        row=0,col=n-1;  //右上角数的坐标
        bool flag=false;  //定义一个标志量,用于记录是否找到,初始化为false
        while(!flag && row<m && col> -1) {
            if(array[row][col]>target) {     //比目标数大,往左查找,列数减一
                col--;
            } else if(array[row][col]<target){     //比目标数小,往下查找,行数加一
                row++;
            } else {
                flag=true; 
                break;
            }
        }
        if(flag){
            return true;
        } else {
            return false;
        }
         
    }
};

2、利用二分查找,即对每一行进行二分查找。这种方法可以解决当你的数组并不是矩阵的情形,即每一行的数字不一样多  O(nlogn) 运行时间比前一种方法长。

class Solution {
public:
    bool Find(int target, vector<vector<int> > array) {
        int row,col,m,n;
        m=array.size();  //求数组的行数
    
        for(row=0;row<m;row++) {
            int low=0;
            int high=array[row].size(); //求对应行的列数 
            while(low<=high) {
                int mid=(low+high)/2;  //第row行的 中间数 
                if(array[row][mid]<target){
                    low=mid+1;   //中间数比目标数小,则在右边 
                } else if(array[row][mid]>target){
                    high=mid-1;  //中间数比目标数大,则在左边 
                } else {
                    return true;
                }
            }
        } 
        return false;
    }
};

 

3、整个矩阵二分法,即利用对角线将矩阵分成上三角和下三角矩阵。再分别对两个三角矩阵进行二分查找.

class Solution {
public:
    bool Find(int target, vector<vector<int> > array){
        if( array.size() == 0 || array[0].size() == 0){  //当矩阵不符合条件时,返回false
            return false;
        }
        int low,high,mid;
        for(int j = 0; j < array.size(); j++){     //判断左下角的数
            low = j;
            high = array.size() - 1;
            mid = (low + high) / 2;
            while(low <= high){
                if(array[mid][j] == target){
                    return true;
                }
                if(array[mid][j] > target){
                    high = mid - 1;
                }else{
                    low = mid + 1;
                }
                mid = (low + high) / 2;
            }
        }

        for(int i = 0; i < array.size() - 1; i++){ //判断右上角的数,i为列数
            low = i + 1;
            high = array[i].size() -1;
            mid = (low + high) / 2;
            while(low <= high){
                if(array[i][mid] == target){
                    return true;
                }
                if(array[i][mid] > target){
                    high = mid - 1;
                }else{
                    low = mid + 1;
                }
                mid = (low + high) / 2;
            }
        }

        return false;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值