剑指Offer算法实现之三:二维数组中的查找

本文介绍了一种在特殊排序的二维数组中查找特定整数的方法。通过从数组的左上角或右下角开始搜索,利用二分的思想,逐步缩小搜索范围,实现了高效的查找过程。文中提供了C++及C语言的实现示例,并通过断言验证了函数的正确性。

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

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

  例如,下面的二维数组。如果在其中查找7则返回true,查找5则返回false:

    1  2   8   9
    2  4   9 12
    4  7 10 13
    6  8 11 15

思路:
  利用“二分”的思想,即在某种程度上能够找到一个数,不在大的那一块,就在小的那一块。因此,可选择从左上角或右下角开始“二分”赛选。

编译环境:ArchLinux+Clang3.3

实现一:C++(使用了C++11的语法)

#include <iostream>
#include <vector>
#include <cassert>
using namespace std;

bool find(vector<vector<int>>& matrix, int e)
{
    bool ret = false;
    int m, n;
    if ( (m = matrix.size()) < 1)
        return ret;
    if ( (n = matrix[0].size()) < 1)
        return ret;
    int i = 0;
    int j = n-1;
    while ( i < m && j >= 0){
        if (matrix[i][j] == e){
            ret = true;
            break;
        } else if (matrix[i][j] < e) { //排除最上面的行
            ++i;
        } else { //排除最右边的列
            --j;
        }
    }
    return ret;
}

int main()
{
    vector<vector<int>> m = { // C++11中,>>之间不再需要空格
        {1, 2, 8, 9},
        {2, 4, 9, 12},
        {4, 7, 10, 13},
        {6, 8, 11, 15}
    };
    assert(find(m, 7));
    assert(!find(m, 20));
}
实现二:C语言版(使用C99 变长数组传参)
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <assert.h>

bool find(int m, int n, int matrix[m][n], int e)
{
    bool ret = false;
    if ( m < 1 || n < 1) return ret;
    int i = 0;
    int j = n - 1;
    while ( i < m && j >= 0 ){
        int c = matrix[i][j];
        if (e == c){
            ret = true;
            break;
        }else if ( e > c){
            i++;
        }else{
            j--;
        }
    }
    return ret;
}

int main()
{
    int m = 4;
    int n = 4;
    int matrix[][4] = { //采用静态数组初始化。因为VLA不能使用初始化器
        {1,2,8,9,},
        {2,4,9,12,},
        {4,7,10,13,},
        {6,8,11,15,},
    };
    assert(find(m, n, matrix, 2)); // VLA传参方式
    assert(!find(m, n, matrix, 0));
}
扩展:

  关于C语言中数组传参,还有两种方式,即用一维数组模拟二维数组和二级指针模拟,后者的典型应用是main函数的char **argv参数


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值