剑指Offer之有序数组查找

一:题目

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

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

二:题目分析

  如题所示,它的行和列都是递增的。那么我们需要试图找到边界点,这个边界点可以帮助我们排除一整行或一整列。

  1. 看左上角的1,比1大的可以是第一列和第一行,所以很难排除一整行或一整列。
  2. 看左下角的6,比6大的数可以确定不在第一列,这样就可以把第一列排除掉。比6小的数,可以确定不在最后一行,可以把第四行排除掉。所以这个边界点满足条件。
  3. 看右下角15,比15小的可以是第四行和第四列,无法排除掉。
  4. 看右上角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确实不在数组内,所以查找失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

非正经程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值