Leetcode Search a 2D Matrix 搜索二维表

本文介绍了一种在具有特定排序属性的二维矩阵中搜索目标值的高效算法,该算法利用二分查找法优化时间复杂度至O(lgm+lgn),并提供详细实现代码。

Search a 2D Matrix


Write an efficient algorithm that searches for a value in anmxnmatrix. This matrix has the following properties:

  • Integers in each row are sorted from left to right.
  • The first integer of each row is greater than the last integer of the previous row.

For example,

Consider the following matrix:

[
  [1,   3,  5,  7],
  [10, 11, 16, 20],
  [23, 30, 34, 50]
]

Giventarget=3, returntrue.

这道题的解法倒是很多的,网上也有不少分析的。

比如LeetCode论坛上有分析非常仔细的,不过他好像推荐的是个O(n+m)的时间效率,这次也是个例外了,他的分析和例子都不好。

因为这道题的最优时间效率应该是O(lgm +lgn); m,n 代表行和列数,而且也没有那么复杂,不过就是考二分法的运用,能够灵活运用了做这道题不是难事,本人一次性通过。

这里是使用二分法,先列二分,然后行二分,看似复杂,其实是很简单的程序。不用看Leetcode上的那么长编大论的分析。

下面是我的程序,看起来长,其实结构很清晰,很好理解的程序。

	const static int FOUND = -2;
	const static int NOT_FOUND = -1;

	bool searchMatrix(vector<vector<int> > &matrix, int target) 
	{
		int found_mark = searchRow(matrix, 0, matrix.size()-1, target);
		if (found_mark == NOT_FOUND) return false;
		if (found_mark == FOUND) return true;

		found_mark = searchCol(matrix, found_mark, 0, matrix[0].size()-1, target);

		if (found_mark == NOT_FOUND) return false;
		return true;
	}

	int searchRow(vector<vector<int> > &m, int low, int up, int tar)
	{
		//up = -1的时候也是等于NOT_FOUND,所以设NOT_FOUND=-1
		if (low > up) return up;

		int mid = low + ((up - low)>>1);
		if (tar < m[mid][0])
		{
			return searchRow(m, low, mid-1, tar);
		}
		else if (m[mid][0] < tar)
		{
			return searchRow(m, mid+1, up, tar);
		}
		else return FOUND;
	}

	int searchCol(vector<vector<int> > &m, int row, int left, int right, int tar)
	{
		if (left > right) return NOT_FOUND;

		int mid = left + ((right - left)>>1);
		if (tar < m[row][mid])
		{
			return searchCol(m, row, left, mid-1, tar);
		}
		else if(m[row][mid] < tar)
		{
			return searchCol(m, row, mid+1, right, tar);
		}
		else return FOUND;
	}


下面也看看Leetcode上的程序,也是很简单的,不过他说这个也许是面试官需要的答案?那我就怀疑了,O(lgn + lgm)比O(n+m)提高了一个档次的时间复杂度啊,当然是二分法好啦。

//属于上下行,左右列夹并追踪目标的方法,复杂度O(n+m)
	bool searchMatrix2(vector<vector<int> > &matrix, int target) {
		int m(matrix.size()-1), n(matrix[0].size()), k(0);
		while(m>=0 && k<n){
			if(matrix[m][k]==target) return true;
			else if(matrix[m][k]>target) --m;
			else ++k;
		}
		return false;
	}

//2004-2-11 update
	bool searchMatrix(vector<vector<int> > &matrix, int target) 
	{
		int row = colSearch(matrix, 0, matrix.size()-1, target);
		if (row == -1) return false;
		return rowSearch(matrix, row, 0, matrix[row].size()-1, target);
	}
	int colSearch(vector<vector<int> > &m, int c1, int c2, int tar)
	{
		if (c1 > c2) return -1;
		int mid = c1 + ((c2-c1)>>1);
		if (m[mid][0]<=tar && tar<=m[mid].back()) return mid;
		if (m[mid][0] < tar) return colSearch(m, mid+1, c2, tar);
		if (tar < m[mid][0]) return colSearch(m, c1, mid-1, tar);
		return -1;
	}
	bool rowSearch(vector<vector<int> > &m, int row, int r1, int r2, int tar)
	{
		if (r1 > r2) return false;
		int mid = r1 + ((r2-r1)>>1);
		if (m[row][mid] < tar) return rowSearch(m, row, mid+1, r2, tar);
		if (tar < m[row][mid]) return rowSearch(m, row, r1, mid-1, tar);
		return true;
	}



(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值