题目:在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否有该整数。
例如,下面的二维数组。如果在其中查找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参数