劍指offer-03:二維陣列(行列遞增)的查詢
阿新 • • 發佈:2019-01-24
一個二維陣列中,每一行都按照從左到右遞增的順序排列,每一列都按照從上往下遞增的順序排列。完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中是否含有該整數。
初看題目,容易想到既然是有序陣列,可按二分的思想查詢。選取某個數字剛和和要查數相等時返回;選取數字小於要查詢的數字,查詢放到當前位置的右方或者下方;若大於要查詢的數字,查詢放在當前位置的上方或者左方。
然而分割槽域後,情況變得複雜,要查詢的區域變成L折行,雖然減小了查詢範圍,但並沒有清晰辦法下一步查詢。陷入其中。
根據二分查詢,第一次砍去一半,剩下的一半在第二次中可以繼續“砍半”操作,這問題逐次是類似的。上述失敗的地方在於兩次問題完全不一樣,越搞越複雜。
考慮:每一行,每一列都是從小到大排列。
我們以每次陣列的第一行的最大值MAX為例討論。
- 當其大於查詢數N時,則MAX為首的列必然都大於N,該列可捨去得到新陣列。
- 當其小於N時,則MAX所在的行可捨去,因為它是該行最大值。
這樣,我們不斷砍去當前陣列的最後一列,或第一行,不斷縮小陣列範圍,直到某次MAX=N找到,或者陣列玩完了沒找到。
同樣,以每一列的最大值查詢,查詢過程和上述方向不一樣罷了。上述從右上角往左下角前進,本段則從左下角往右上角前進。
我們不能從左上角,右下角找起,因為這樣帶來不確定。
實際上述查詢思想正是二分法。這樣來看待陣列:
9恰好是紅線序列的中值,捨去後新的藍線序列也是增序。我們始終在做二分查詢。所以效率很高。
程式碼:
#include "stdafx.h"
#include <iostream>
using namespace std;
bool Find(int * matrix, int rows, int columns, int number)
{
bool found = false;
if (matrix != nullptr && rows > 0 && columns > 0)
{
int row = 0;
int column = columns - 1;
// 迴圈到頭沒找到返回
while (row < rows && column >= 0)
{
// 找到返回
if (matrix[row*columns + column] == number)
{
found = true;
break;
}
// 大於查詢值,該列捨去,仍為二維陣列
else if (matrix[row*columns + column] > number)
--column;
// 小於查詢值,該行捨去,仍為二維陣列
else
++row;
}
}
return found;
}
int main()
{
int a[4][4] = { {1, 2, 8, 9},
{2, 4, 9, 12},
{4, 7, 10, 13},
{6, 8, 11, 15}
};
cout << Find((int *)a, 4, 4, 3) << endl;
return 0;
}