10.9 排序矩阵查找

     《程序员面试金典》(第六版)习题:仅为记录一下以加强印象,不为商业用途,如有侵权请联系删除。以下源码和解释参考了书中源码以及解释。
     基础算法利用到了排序矩阵的特殊性质,如果待查找元素小于一列开头的元素则待查找元素肯定不会位于该列右边的列以及该列本身。如果待查找元素小于一行末尾的元素则待查找元素肯定不会位于该行上边的行以及该行本身。基础算法从矩阵第0行最后一个元素开始搜索,不断向左下角行进来找到待查找元素。

//基础算法
bool findElement(vector<vector<int>> matrix,int elem)
{
	int row = 0;
	int col = matrix[0].size() - 1;
	while (row< matrix.size()&&col>=0)
	{
		if (matrix[row][col]==elem)
		{
			return true;
		}
		else if (matrix[row][col] > elem)
		{
			col--;
		}
		else
		{
			row++;
		}
	}
	return false;
}

     改进算法充分利用到了排序矩阵的特殊性质,算法首先沿着对角线利用二分查找算法寻找需要查找的元素,如果找到需要查找的元素就直接返回,否则找到对角线上第一个比需要查找的元素大的元素,然后以此元素为基点将原矩阵划分为两块面积更小的矩阵并递归在这两块矩阵上查找。

//改进算法
int min(int a,int b)
{
	if (a > b)
		return b;
	else
		return a;
}

class Coordinate
{
public:
	int row;
	int column;
	bool isFinded;
	Coordinate(int r, int c)
	{
		row = r;
		column = c;
		isFinded = false;
	}

	bool inbounds(vector<vector<int>> matrix)
	{
		return 	((row >= 0) && (column >= 0) && (row < matrix.size()) && (column < matrix[0].size()));
	}

	bool isBefore(Coordinate p)
	{
		return row <= p.row && column <= p.column;
	}

	void moveDownRight()
	{
		row++;
		column++;
	}

	void setToAverage(Coordinate min, Coordinate max)
	{
		row = (min.row + max.row) / 2;
		column = (min.column + max.column) / 2;
	}
};
Coordinate findElement(vector<vector<int>> matrix, Coordinate origin, Coordinate dest, int x);

Coordinate findElement(vector<vector<int>> matrix, int x)
{
	Coordinate origin(0, 0);
	Coordinate dest(matrix.size() - 1, matrix[0].size() - 1);
	return findElement(matrix, origin, dest, x);
}

Coordinate  partitionAndSearch(vector<vector<int>> matrix, Coordinate origin, Coordinate dest, Coordinate pivot, int x)
{
	Coordinate lowerLeftOrigin(pivot.row, origin.column);
	Coordinate lowerLeftDest(dest.row, pivot.column - 1);
	Coordinate upperRightOrigin(origin.row, pivot.column);
	Coordinate upperRightDest(pivot.row - 1, dest.column);
	
	Coordinate  lowerLeft = findElement(matrix, lowerLeftOrigin, lowerLeftDest, x);
	if (!lowerLeft.isFinded)
	{
		return findElement(matrix, upperRightOrigin, upperRightDest, x);
	}
	return lowerLeft;
}

Coordinate  findElement(vector<vector<int>> matrix, Coordinate origin, Coordinate dest, int x)
{
	if (!origin.inbounds(matrix) || !dest.inbounds(matrix)) 
	{
		origin.isFinded = false;
		return origin;
	}
	if (matrix[origin.row][origin.column] == x) 
	{
		cout << "elements find!!!!!!!!!" << endl;
		cout << "row=" << origin.row << " column=" << origin.column << endl;
		origin.isFinded = true;
		return origin;

	}
	else if (!origin.isBefore(dest)) 
	{
		origin.isFinded = false;
		return origin;
	}

	/* Set start to start of diagonal and end to the end of the diagonal. Since
	 * the grid may not be square, the end of the diagonal may not equal dest.
	 */
	Coordinate start = origin;
	int diagDist = min(dest.row - origin.row, dest.column - origin.column);
	Coordinate end(start.row + diagDist, start.column + diagDist);
	Coordinate p(0, 0);
	
	/* Do binary search on the diagonal, looking for the first element greater than x */
	while (start.isBefore(end)) 
	{
		p.setToAverage(start, end);

        if (x > matrix[p.row][p.column]) 
		{
			start.row = p.row + 1;
			start.column = p.column + 1;
		}
		else if(x < matrix[p.row][p.column])
		{
			end.row = p.row - 1;
			end.column = p.column - 1;
		}
		//对于部分对角线上的元素可以快速找到
        else if (x == matrix[p.row][p.column])
        {
   	        cout << "elements fast find!!!!!!" << endl;
   	        cout << "row=" << p.row << " column=" << p.column << endl;
   	        p.isFinded = true;
   	        return p;
        }
	}
	/* Split the grid into quadrants. Search the bottom left and the top right. */
	return partitionAndSearch(matrix, origin, dest, start, x);
}

//测试程序
int main()
{
	vector<vector<int>> matrix = { {15, 30,  50,  70,  73},
						           {35, 40, 100, 102, 120},
						           {36, 42, 105, 110, 125},
						           {46, 51, 106, 111, 130},
						           {48, 55, 109, 140, 150} };

	int m = matrix.size();
	int n = matrix[0].size();

	int count = 0;
	int littleOverTheMax = matrix[m - 1][n - 1] + 10;
	for (int i = 0; i < littleOverTheMax; i++) 
	{
		Coordinate c = findElement(matrix, i);
		if (c.isFinded) 
		{
			cout<<i<<": ("<<c.row<<", "<<c.column<<")"<<endl;
			count++;
		}
	}
	cout << "Found " << count << " unique elements." << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

qqssss121dfd

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

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

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

打赏作者

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

抵扣说明:

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

余额充值