问题描述:
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
, returntrue
.
释义:在给定的 m X n 二维数组中搜索,判断是否存在target,数组每行有序, 非递减顺序,下一行的第一个元素比上一个元素的最后一个元素大,算法没有要求。
问题分析:
1. 可以把二维数组的看作是一个有序的一位数组,即按行追加到上一行的末尾位置处,开辟一个大小为m+n大小的以为数组,利用二分法检索target,算法时间复杂度为O(logn),空间复杂度为O(m+n)。
2. 先顺序检索到target所在的行位置(row index),然后在这一行中利用二分查找进行检索,时间复杂度为O(n),由于无需开辟额外数组,所以空间复杂度为O(1);
3. 先二分检索到target所在的行位置(row index), 然后在这一行利用二分检索,时间复杂度为O(log n), 空间复杂度为O(1);
4. 确定边界条件和异常情况;
实现:
i.顺序检索行:
/*
* @brief: search the "target" in the "sorted" Matrix which
* the first integer of each row is greater than the last integer of the previous row.
* @authour: zhangjinxing jinxingbay@163.com
* @time: 2015 01 04, 21 15
* @edition: 1.0
* @time complexity: O(n), can be "{optimized}" to O(log n) by using "{Binary Search}"
*/
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
const unsigned int m = matrix.size();
if (0 == m) {// matrix is empty, row number == 0
return false;
}
const unsigned int n = matrix[0].size();
if (0 == n) {// matrix is empty, row number != 0, but column number == 0
return false;
}
if (target < matrix[0][0] || target > matrix[m-1][n-1]) {// target is not in the matrix
return false;
}
unsigned int i=0, j=0, irow=0;// irow is the index of the choosen row
for (i=0; i<m; ++i) {// find the "target" row number
irow = i;// change the irow in case of "target" is existed in the last row
if (matrix[i][0] == target) {// return true if find the "target" in the matrix
return true;
}
if (matrix[i][0] > target) {// increasing index "i" while matrix[i][0] larger than target, return the previous row "i-1"
irow = i - 1;
break;
}
}
if (target < matrix[irow][0] || target > matrix[irow][n-1]) {// target is not in the matrix row where row index == irow
return false;
}
for (j=0; j<n; ++j) {// find the "target" column number
if (matrix[irow][j] == target) {// return true if find the "target" in the matrix row index == irow
return true;
}// else, increasing index "i" while not equals to "target"
}
return false;// if can not find the "target" in the matrix, return false
}
};
分析
先进行边界条件判断会提高程序运行效率,提高可维护性;如编码加粗部分。
ii. 二分检索行
/*
* @brief: search the "target" in the "sorted" Matrix which
* the first integer of each row is greater than the last integer of the previous row.
* @authour: zhangjinxing jinxingbay@163.com
* @time: 2015 01 04, 21 35
* @edition: 2.0
* @time complexity: O(long n) by using "{Binary Search}"
*/
class Solution {
public:
bool searchMatrix(vector<vector<int> > &matrix, int target) {
const unsigned int m = matrix.size();
if (0 == m) {// matrix is empty, row number == 0
return false;
}
const unsigned int n = matrix[0].size();
if (0 == n) {// matrix is empty, row number != 0, but column number == 0
return false;
}
if (target < matrix[0][0] || target > matrix[m-1][n-1]) {// target is not in the matrix
return false;
}
unsigned int row=0;// irow is the index of the choosen row
unsigned int rbeg=0, rend=m-1, rmd=m/2;
while (rbeg<=rend) {
if (rbeg == rend) {
irow = rend;
break;
}
rmd = rbeg + (rend-rbeg + 1) / 2; // pay attention on the index computing when "begin index" and "end index" changing
// when using "Binary Search"
if (matrix[rmd][0] == target) {
return true;
}
if (matrix[rmd][0] > target) {// row index must be in the range "[rbeg, rmd-1]"
rend = rmd - 1;
continue;
}
if (matrix[rmd][0] < target) {
rbeg = rmd;// row index must be in the range "[rmd, rend]", attention "rmd" not "rmd+1"
continue;
}
}
if (target < matrix[irow][0] || target > matrix[irow][n-1]) {// target is not in the matrix row where row index == irow
return false;
}
unsigned int cbeg=0, cend=n-1, cmd=n/2;
while (cbeg<=cend) {
if (cbeg == cend) {
if (matrix[irow][cbeg] == target) {
return true;
} else {// can not find the "target" in the matrix,
// "target > matrxi[irow][0] && target < matrix[irow][n-1], but no one equal to target"
return false;
}
}
cmd = cbeg + (cend-cbeg+1) / 2; // pay attention on the index computing when "begin index" and "end index" changing
// when using "Binary Search"
if (matrix[irow][cmd] == target) {
return true;
}
if (matrix[irow][cmd] > target) {// "[cbeg, cmd-1]"
cend = cmd - 1;
continue;
}
if (matrix[irow][cmd] < target) {// "[{cmd+1}, cend]" not "cmd"
cbeg = cmd + 1;
continue;
}
}
return false;// if can not find the "target" in the matrix, return false
}
};
分析:
二分法使用时一定要注意分开的两个区间的下标。总结
i. consider special cases completely, using the whole given conditions;
ii. build the bug-free coding fragment is difficult, to be there, I must do exercises, coding & thinking;
iii. pay attention to the index when using Binary Search method;
iv. special cases comes first and just "code" it.
-----One "Acceptance" a day, keep my mind awake.-----noted by bayingbf-----2015.01.05-----