【剑指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)。

 

本文完。

posted @ 2015-06-12 08:09  Stephen_Hsu  阅读(298)  评论(0编辑  收藏  举报