//忽略代码风格...大小写比较随意了
private static final int[][] matrix = {
{1, 2, 4, 5, 6, 7},
{3, 4, 7, 8, 9, 10},
{4, 5, 8, 12, 14, 16},
{4, 6, 9, 14, 15, 17},
};
/**
* 在二维数组中查找某个数是否存在
* 次二维数组横向与纵向都是单调递增的
*/
public static boolean testFindValueInMatrix01(int[][] matrix, int key) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix01 key=" + key);
int rowCount = matrix.length;
int columnCount = matrix[0].length;
if (key < matrix[0][0]) {
return false;
} else if (key > matrix[matrix.length - 1][matrix[0].length - 1]) {
return false;
} else {
for (int i = 0; i < rowCount; i++) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix01 i=" + i);
if (key > matrix[i][columnCount - 1] || key < matrix[i][0]) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix01 continue");
continue;
} else {
for (int j = columnCount - 1; j >= 0; j--) {
if (key == matrix[i][j]) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix01 find it "+"("+i+","+j+")");
return true;
}
}
}
}
}
return false;
}
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 key=14
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 i=0
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 continue
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 i=1
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 continue
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 i=2
01-13 13:00:56.284 28607-28607/? I/testFindValueInMatrix: testFindValueInMatrix01 find it (2,4)
思路:
1.先与左上角的数字and 右下角的数字 对比,如果不在范围内直接false;
2.与第一行最左 and最右的数字对比,不在范围内,直接continue换下一行;
3.如果‘可能’在行内,那么遍历这一行;
4.如果不在行内,进行下一行的遍历;
ps:还有更好的方式,待续
方法2:
public static boolean testFindValueInMatrix03(int[][] matrix,int key){
int i = 0, j = matrix[0].length - 1;
int var = matrix[i][j];
while (i < matrix.length && j >= 0){
if (var == key) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix03 find it " + "(" + i + "," + j + ")");
return true;
}else if (var < key) {
var = matrix[++i][j];
}else {
var = matrix[i][--j];
}
}
return false;
}
网上有人叫上面这个方法是‘定位法’,这个方法其实是前一个方法的变种,从右上角那个数开始比较,如果右上角的数比key大,那么就向左走,如果右上角的数比key小,就向下走;拿14为例,右上角的数比14小,所以一路向下走到第三行,16比14大,想走走,14刚好找到。
方法3:
采用递归+二分法 的方式。
public static boolean testFindValueInMatrix02(
int left,
int right,
int top,
int bottom,
int[][] matrix,
int key) {
Log.i("testFindValueInMatrix", "testFindValueInMatrix02 key=" + key);
int midCol = (left+right)>>1;
int midRow = (top+bottom)>>1;
Log.i("testFindValueInMatrix", "testFindValueInMatrix02 left="+left+
"--right="+right+
"--top="+top+
"--bottom="+bottom+
"--midCol="+midCol+
"--midRow="+midRow);
Log.i("testFindValueInMatrix", "testFindValueInMatrix02 midValue=" + matrix[midRow][midCol]);
if(left>right || top>bottom || midCol > right || midRow > bottom){
return false;
}
if(key > matrix[bottom][right]){
return false;
}else if(key < matrix[top][left]){
return false;
}else{
if(key>matrix[midRow][midCol]){
return testFindValueInMatrix02(
midCol+1,
right,
midRow+1,
bottom,
matrix,
key) ||
testFindValueInMatrix02(
midCol+1,
right,
top,
midRow,
matrix,
key) ||
testFindValueInMatrix02(
left,
midCol,
midRow+1,
top+bottom,
matrix,
key);
}else if (key<matrix[midRow][midCol]){
return testFindValueInMatrix02(
left,
midCol-1,
top,
midRow-1,
matrix,
key) ||
testFindValueInMatrix02(
midCol,
right,
top,
midRow-1,
matrix,
key) ||
testFindValueInMatrix02(
left,
midCol-1,
midRow,
bottom,
matrix,
key);
}else{
Log.i("testFindValueInMatrix", "testFindValueInMatrix02 find it "+"("+(midRow)+","+(midCol)+")");
return true;
}
}
}
这个方法我简单测试,是没问题的。思路就是:根据二分法查看key在哪个区域,然后在那个区域回调查找,如图:
例如第一个mid位置的值是7,查找14,14>7,那么就在A,B,C三个区域再次查找。