(每日算法)LeetCode---Search a 2D Matrix(查找元素是否存在)

通过二分查找查找元素是否存在矩阵中。这也是二分查找的具体应用,思想不变,但是细节上需要变化。

Write an efficient algorithm that searches for a value in an m x n matrix. 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]
]

Given target = 3, return true.

class Solution {
public:
   bool searchMatrix(vector<vector<int> > &matrix, int target) {
  	if(matrix.size() == 0)   return false;
  	int m = matrix.size();
	int n = matrix[0].size();

	if(target < matrix[0][0] || target > matrix[m-1][n-1]) //目标元素不在矩阵中
		return false;

	int low = 0, high = m - 1;//在行间和行内查找时共用这两个元素,表示当前查找的子范围
	int medium;
	while(low <= high )   //通过二分查找确认元素在medium行中
	{
	    medium = low + (high - low)/2;
		
		if(target < matrix[medium][0])
		{high = medium - 1;continue;}
		if(target > matrix[medium][n - 1])
		{low = medium + 1;continue;}
		//因为查找的是范围,容易导致while死循环,所以两个条件不满足的时候,
		//且target不在medium行中的时候,就是target元素不存在,不用再查找了
		if(matrix[medium][0] <= target && matrix[medium][n - 1] >= target)
			break;
		else
			return false;   
		
	}
	//经过上述步骤能确认target所在的那一行,即medium
	//接下来在medium行中查找有无target
	low = 0;
	high = n - 1;
	while(low <= high )//常规的二分查找
	{
		int medium_num = low + (high - low)/2;
		if(matrix[medium][medium_num] == target)
			return true;
		if(matrix[medium][medium_num]  < target)
			low = medium_num + 1;
		if(matrix[medium][medium_num] > target)
			high = medium_num - 1;
	}
	
	return false;
    }
};

有一种更易懂的方法,如下:

class Solution {
public:
bool searchMatrix(const vector<vector<int>>& matrix, int target) {
	if (matrix.empty()) return false;
	const size_t m = matrix.size();
	const size_t n = matrix.front().size();//每行元素的数量
	int first = 0;
	int last = m * n;
	while (first < last) {
		int mid = first + (last - first) / 2;
		int value = matrix[mid / n][mid % n];//mid所指元素的值
		if (value == target)
			return true;
		else if (value < target)
			first = mid + 1;
		else
			last = mid;
		}
	return false;
	}
};

上面的方法把所有的元素都看做一列,vector本质上也是一维数组的,所以没什么不妥。

第一种方法对所在行也进行二分检索,看似检索的次数比较少,但是要比较两个元素,访问次数也是不低的。

而二分检索的复杂度是对数时间,比较的次数还是比较少的。因此,这里考虑成一维数组还是比较合理的。

效率更高,时间更短。也更好理解。

知识点阐述:

std::vector::front

reference front();
const_reference front() const;
Access first element
Returns a reference to the first element in the  vector. Unlike member  vector::begin , which returns an iterator to this same element, this function returns a direct reference.

Calling this function on an  empty  container causes undefined behavior.

Return value

A reference to the first element in the  vector  container.

If the  vector  object is const-qualified, the function returns a  const_reference . Otherwise, it returns a  reference .

// vector::front
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  myvector.push_back(78);
  myvector.push_back(16);

  // now front equals 78, and back 16

  myvector.front() -= myvector.back();

  std::cout << "myvector.front() is now " << myvector.front() << '\n';

  return 0;
}
Output:
myvector.front() is now 62





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值