需求:
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都是按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。如果含有该整数则把整数所在的行和列输出。
例如一个二维数组:
1 2 8 9
2 4 9 12
4 7 10 13
6 8 11 15
要查找的整数为 7
输出的结果应该是 3行2列
分析:
思路一
按照最简单的办法,从二维数组第一个元素从左到右从上到下开始遍历,直到找到或者遍历到最后一个元素找不到的情况。暂且把这种方法称之为从头遍历法吧。如果是m行n列的数组,则这种方法的时间复杂度是O(m*n)。请看示例代码findKeyFromHead
思路二
更高效的查找方法,从右上角开始遍历,暂且命名为右上角查找法吧。要找的整数是7,先比较右上角第一个元素9,
1.比较7和9,由于7比9小,数组左边的数比较小,下边的数比较大,因此7只能在9的左边;
2.比较7和8,由于7比8小,跟上面一样,7只能在8的左边;
3.比较7和2,由于7比2大,数组左边的数比较小,下边的数比较大,因此7只能在2的下边;
4.比较7和4,由于7比4大,跟上面一样,因此7只能在4的下边;
5.比较7和7,发现找到了结束循环。
如果比较过程中出现行数或者列数其中之一到0了还是找不到,说明这个数就不在数组中了。
右上角查找法每次比较都能排除调一整行或者一整列,时间复杂度是O(m+n)。
请看示例代码findKeyFromRrightHead
总结:
由于从头遍历法,每次只能排除一个元素,而右上角查找法每次能排除一整行和一整列,因此显而易见右上角查找法的效率会比较高。(PS.左下角查找法原理类似)
c++示例代码:
1 #include <iostream> 2 3 using namespace std; 4 5 const int g_matrixRow = 4; 6 const int g_matrixColumn = 4; 7 8 /************************************************************************/ 9 /* @brif 从头遍历法查找二维数组关键字 10 /* @param matrix 用于查询的二维数组 11 /* @param row 二维数组的行数 12 /* @param column 二维数组的列数 13 /* @param key 需要查询的关键字 14 /* @param retRow 关键字所在行(查询失败为默认值-1) 15 /* @param retColumn 关键子所在列 (查询失败为默认值-1) 16 /* @return true表示查找到 false表示查找失败 17 /************************************************************************/ 18 bool findKeyFromHead(const int *matrix, const int row, const int column, const int key, int& retRow, int& retColumn) 19 { 20 bool bFoud = false; 21 retRow = -1; 22 retColumn = -1; 23 24 if (!matrix || row < 1 || column < 1 || !retRow || !retColumn) 25 { 26 return bFoud; 27 } 28 29 for (int i = 0; i < row; ++i) 30 { 31 for (int j = 0; j < column; ++j) 32 { 33 //判断matrix[i][j]是不是跟key相同 34 if (*(matrix+(i*column)+j) == key) 35 { 36 bFoud = true; 37 //计算机索引从0开始,转换成真正的行数和列数 38 retRow = i + 1; 39 retColumn = j + 1; 40 break; 41 } 42 } 43 } 44 return bFoud; 45 } 46 47 /************************************************************************/ 48 /* @brif 右上角查找法查找二维数组关键字 49 /* @param matrix 用于查询的二维数组 50 /* @param row 二维数组的行数 51 /* @param column 二维数组的列数 52 /* @param key 需要查询的关键字 53 /* @param retRow 关键字所在行(查询失败为默认值-1) 54 /* @param retColumn 关键子所在列 (查询失败为默认值-1) 55 /* @return true表示查找到 false表示查找失败 56 /************************************************************************/ 57 bool findKeyFromRrightHead(const int *matrix, const int row, const int column, const int key, int& retRow, int& retColumn) 58 { 59 bool bFoud = false; 60 retRow = -1; 61 retColumn = -1; 62 63 if (!matrix || row < 1 || column < 1 || !retRow || !retColumn) 64 { 65 return bFoud; 66 } 67 68 //从右上角开始查找,即第一个比较的原始是matrix[0][column-1] 69 int tmpRow = 0; 70 int tmpColumn = column - 1; 71 72 //如果行数和列数都是合法的就一直循环 73 while (tmpColumn >= 0 && tmpRow >= 0) 74 { 75 //判断matrix[tmpRow][tmpColumn]与关键字是否相等 76 int curKey = *(matrix + column * tmpRow + tmpColumn); 77 //相等表示找到了,保存当前的和列,退出循环 78 if (key == curKey) 79 { 80 //计算机索引从0开始,转换成真正的行数和列数 81 retRow = tmpRow + 1; 82 retColumn = tmpColumn + 1; 83 bFoud = true; 84 break; 85 } 86 //关键字比当前的值大,说明在下边的行 87 else if (key > curKey) 88 { 89 tmpRow += 1; 90 } 91 //关键字比当前的值小,说明在左边的列 92 else 93 { 94 tmpColumn -= 1; 95 } 96 } 97 98 return bFoud; 99 } 100 101 int main() 102 { 103 int matrix[g_matrixRow][g_matrixColumn] = { {1,2,8,9}, {2,4,9,12}, {4,7,10,13}, {6,8,11,15} }; 104 105 cout << g_matrixRow << "行" << g_matrixColumn << "列的二维数组:" << endl << endl;; 106 for (int i = 0; i < g_matrixRow; ++i) 107 { 108 for (int j = 0; j < g_matrixColumn; ++j) 109 { 110 cout << matrix[i][j] << "\t"; 111 } 112 cout << endl; 113 } 114 cout << endl; 115 116 int key = 7; 117 int retRow = 0, retColumn = 0; 118 119 bool bResult = findKeyFromHead((const int*)matrix, g_matrixRow, g_matrixColumn, key, retRow, retColumn); 120 121 cout << "从头遍历法" << endl; 122 if (bResult) 123 { 124 cout << "关键字" << key << "在:"<< retRow << "行" << retColumn << "列" << endl; 125 } 126 else 127 { 128 cout << "关键字" << key << "没找到" << endl; 129 } 130 131 bResult = findKeyFromRrightHead((const int*)matrix, g_matrixRow, g_matrixColumn, key, retRow, retColumn); 132 133 cout << endl << "右上角查找法" << endl; 134 if (bResult) 135 { 136 cout << "关键字" << key << "在:" << retRow << "行" << retColumn << "列" << endl; 137 } 138 else 139 { 140 cout << "关键字" << key << "没找到" << endl; 141 } 142 143 cout << endl; 144 return 0; 145 }
测试结果: