//忽略代碼風格...大小寫比較隨意了
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三個區域再次查找。