zoukankan      html  css  js  c++  java
  • 【剑指offer】面试题三:二维数组中的查找

    题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
    
    例如下面的二维数组就是每行、每列都递增排序。如果在这个数组中查找数字 7,则返回 true;如果查找数字 5, 由于数组不含有该数字,则返回false。
    
    1    2     8    9
    
    2    4     9    12
    
    4    7    10    13
    
    6    8    11    15

    解法一:遍历整个二维数组

    这种思路演变为二维数组的遍历,由于内外两个 for 循环,因此时间复杂度为 O(N*N);

    代码如下:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 bool find(int *matrix, int rows, int cols, int num)
     5 {
     6     if(matrix == NULL || rows <= 0 || cols <= 0
     7         || num < matrix[0] || num > matrix[rows*cols-1])
     8         return false;
     9 
    10     for(int i = 0; i < rows; ++i)
    11     {
    12         for(int j = 0; j < cols; ++j)
    13         {
    14             if(num == matrix[i*cols+j])
    15                 return true;
    16         }
    17     }
    18     return false;
    19 }
    20 
    21 int main(int argc, char *argv[])
    22 {
    23     int arr[4][4] = {1, 2, 8, 9, 2, 4, 9, 12, 4, 7, 10, 13, 6, 8, 11, 15};
    24     bool isFind = find((int*)arr, 4, 4, 7);
    25     cout << "isFind: " << isFind << endl;
    26     return 0;
    27 }
    View Code

    解法二:利用该二维数组的特性

    思路:我们选择数组最右上角的数字与num比较;

    列:假设该 num 为 7,由于 9 > 7,因此根据数组列元素的递增规律,最右列的所有元素都大于 7,所以我们可以把最右列从需要考虑的区域内剔除(变量 col-- 即可);

    行:假设该 num 为 10,由于 9 < 10,因此根据数组行元素的递增规律,第一行的所有元素都小于 10,所以我们可以把第一行从需要考虑的区域内剔除(变量 row++ 即可)。

    以下为 num 为 7 时所查找的过程:

    注:矩阵中加阴影背景的区域是下一个要查找的范围

    把整个查找过程分析清楚之后,我们不难写出如下代码:

     1 // findNum.cpp
     2 #include <iostream>
     3 using namespace std;
     4 
     5 bool find(int *matrix, int rows, int cols, int num)
     6 {
     7     if(matrix == NULL || rows <= 0 || cols <= 0
     8         || num < matrix[0] || num > matrix[rows*cols-1])
     9         return false;
    10 
    11     int row = 0, col = cols-1;
    12     while(row < rows && col >= 0)
    13     {
    14         if(matrix[row*cols+col] == num)
    15             return true;
    16         else if(matrix[row*cols+col] > num)
    17             col--;
    18         else
    19             row++;
    20     }
    21 
    22     return false;
    23 }
    24 
    25 int main(int argc, char *argv[])
    26 {
    27     int arr[4][4] = {1, 2, 8, 9, 2, 4, 9, 12, 4, 7, 10, 13, 6, 8, 11, 15};
    28 
    29     for(int i = 0; i < 20; ++i)
    30     {
    31         bool isFind = find((int*)arr, 4, 4, i);
    32         cout << i << " isFind: " << isFind << endl;
    33     }
    34     return 0;
    35 }
    View Code
    注:while结束的条件为当行变量 row(从0开始)等于或大于给出的总行数rows;或者列变量col(从 cols-1开始)小于0时,循环结束。

    编译与执行:

    1 g++ -o findNum findNum.cpp
    2 ./findNum

    性能分析:

    从以上代码可知每循环一次,我们都会减掉一列或者一行,直到找到该num为止,因此时间复杂度为O(N)。

    本文完。

  • 相关阅读:
    [转]C#汉字转拼音的源码
    [转]C# DES 加密/解密类库,支持文件和中文/UNICODE字符,返回BASE64编码字符串
    48瓶子,48种性格
    “识谎”36计
    巧克力有益智商 经常吃可提高大脑计算能力
    调用方未由服务进行身份验证
    揭秘人体24小时使用手册
    [转]C#实现人民币金额小写转大写的代码
    转一篇绝对详细的手工构造PE文件教程
    bat 查找某个进程的ID号
  • 原文地址:https://www.cnblogs.com/xfxu/p/4568233.html
Copyright © 2011-2022 走看看