一:题目
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15
二:题目分析
如题所示,它的行和列都是递增的。那么我们需要试图找到边界点,这个边界点可以帮助我们排除一整行或一整列。
- 看左上角的1,比1大的可以是第一列和第一行,所以很难排除一整行或一整列。
- 看左下角的6,比6大的数可以确定不在第一列,这样就可以把第一列排除掉。比6小的数,可以确定不在最后一行,可以把第四行排除掉。所以这个边界点满足条件。
- 看右下角15,比15小的可以是第四行和第四列,无法排除掉。
- 看右上角9,同样的,比9大的可以排除第一行,比9小的可以排除第四列。
那么综上,我们可以选取左下角或右上角作为第一个判断边界,依次排除掉整列或整行,这样逐步减少查找范围,最终找到我们需要的数字。
以查找数字7为例子,它的演变过程如下:
a) 9大于7所以将第四列排除掉,查找范围如下:
1 2 8
2 4 9
4 7 10
6 8 11
b) 8大于7所以将第三列排除掉,查找范围如下:
1 2
2 4
4 7
6 8
c) 2小于7所以将第一行排除掉,查找范围如下:
2 4
4 7
6 8
d) 4小于7所以将第二行排除掉,查找范围如下:
4 7
6 8
这样就找了数字7。
三:源码
bool Find(int* pMatrix, int nRows, int nColumns, int nNumber) {
if (pMatrix == nullptr || nRows <= 0 || nColumns <= 0 ) {
return false;
}
//first compare right corner
bool bFind = false;
int nCurRow = 0;
int nCurColumn = nColumns - 1;
while (nCurRow < nRows && nCurRow >=0) {
int nCurIndex = nCurRow * nColumns + nCurColumn;
if (pMatrix[nCurIndex] > nNumber) {
nCurColumn--;
continue;
}
if (pMatrix[nCurIndex] < nNumber) {
nCurRow++;
continue;
}
if (pMatrix[nCurIndex] == nNumber) {
bFind = true;
break;
}
}
return bFind;
}
如上二维数字其实是一个一维数组,在内存上是连续的。所以这里通过计算索引获取数组中的数字位置进行判断。代码比较简单这里就不过多赘述了。
四:测试
对代码进行测试如下:
void TestFindMatrix() {
int matrix[] = {
2, 5, 8, 9,12,
8, 6, 10, 11,13,
11, 18, 19, 20,30,
15, 19, 20, 31,32,
};
int nNumber = 33;
bool bFind = Find(matrix, 4, 5, nNumber);
std::string strResult = (bFind == true ? "successful" : "failed");
printf("find %s: %d\n", strResult.c_str(), nNumber);
}
运行结果:
33确实不在数组内,所以查找失败。