LeetCode剑指offer 04 二维数组中的查找(c++)

本文介绍了如何在按特定顺序排列的二维数组中高效查找数字。首先提出暴力查找方法,然后利用数组的排序特性实现线性查找,将时间复杂度降低到O(m+n)。并提供了完整测试代码验证两种方法的正确性。


题目要求

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

示例:

现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]

给定 target = 5,返回 true(即找到该数字)。
给定 target = 20,返回 false(即未找到该数字)。

限制:
0 <= n <= 1000
0 <= m <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof

下面展示的解法代表了我对题目的处理思路——首先是自己思考的解法(可能是暴力解法),然后综合leetcode部分题解和论坛上的其他回答写出的较优化解法。


一、基础解法——暴力查找

如果该二维数组没有任何特性,暴力解法可能就是最通用的解法。他的做法就是挨个扫描每行(n)每列(m)的每个元素,如果与目标值相等,返回true,如果遍历完所有元素均没有与目标值相等的,则返回false。代码如下:

bool findNumberIn2DArray01(vector<vector<int>>& matrix, int target)
{
	if (matrix.size() == 0 || matrix[0].size() == 0)
	{
		return false;
	}
	for (int i = 0; i < matrix.size(); i++)
	{
		for (int j = 0; j < matrix[0].size(); j++)
		{
			if (matrix[i][j] == target)
			{
				return true;
			}
		}
	}
	return false;
}

![在这里插入图片描述](https://img-blog.csdnimg.cn/20201030215428657.png#pic_cent

时间复杂度O(n*m)。

二、数字规律——线性查找

根据条件“每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序”,可以直到二维数组的横向和竖向都是有序的,根据这一特性能够很快确定一颗以。

代码如下:

bool findNumberIn2DArray02(vector<vector<int>>& matrix, int target)
{
	if (matrix.size() == 0 || matrix[0].size() == 0)
	{
		return false;
	}
	int n = matrix.size() - 1, m = matrix[0].size() - 1;
	int i = 0, j = m;
	while (i <= n && j >= 0)
	{
		if (target == matrix[i][j])
		{
			return true;
		}
		else if (target < matrix[i][j])
		{
			j--;
		}
		else if (target > matrix[i][j])
		{
			i++;
		}
	}
	return false;
}

在这里插入图片描述
时间复杂度:O(m+n)。

三、完整测试代码

#include <iostream>
#include <vector>
using namespace std;

//方法一:暴力法
bool findNumberIn2DArray01(vector<vector<int>>& matrix, int target)
{
	if (matrix.size() == 0 || matrix[0].size() == 0)
	{
		return false;
	}
	for (int i = 0; i < matrix.size(); i++)
	{
		for (int j = 0; j < matrix[0].size(); j++)
		{
			if (matrix[i][j] == target)
			{
				return true;
			}
		}
	}
	return false;
}

//方法二:线性查找
bool findNumberIn2DArray02(vector<vector<int>>& matrix, int target)
{
	if (matrix.size() == 0 || matrix[0].size() == 0)
	{
		return false;
	}
	int n = matrix.size() - 1, m = matrix[0].size() - 1;
	int i = 0, j = m;
	while (i <= n && j >= 0)
	{
		if (target == matrix[i][j])
		{
			return true;
		}
		else if (target < matrix[i][j])
		{
			j--;
		}
		else if (target > matrix[i][j])
		{
			i++;
		}
	}
	return false;
}

int main()
{
	/*
	测试用例
		[
			[1, 4, 7, 11, 15],
			[2, 5, 8, 12, 19],
			[3, 6, 9, 16, 22],
			[10, 13, 14, 17, 24],
			[18, 21, 23, 26, 30]
		]
	给定 target  = 5,返回 true。
	给定 target  = 20,返回 false。
	限制:
		0 <= n <= 1000
		0 <= m <= 1000
	*/
	vector<vector<int>> vTest = {
		{1,4,7,11,15},
		{2,5,8,12,19},
		{3,6,9,16,22},
		{10,13,14,17,24},
		{18,21,23,26,30}	
	};
	int target01 = 5;
	int target02 = 20;

	//方法一:暴力查找
	cout << findNumberIn2DArray01(vTest, target01) << endl;
	cout << findNumberIn2DArray01(vTest, target02) << endl;

	//方法二:线性查找
	cout << findNumberIn2DArray02(vTest,target01) << endl;
	cout << findNumberIn2DArray02(vTest, target02) << endl;

	system("pause");
	return 0;
}

总结

此外,在浏览其他做法时,发现还有使用二分法和递归的方法来解的,但是十分复杂不好理解,并且从算法复杂度的角度来看,并不是十分的优化,这里不列出来,感兴趣的可以去搜索查看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Claude的羽毛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值