題意描述:
在一個 n * m 的二維數組中,每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。
示例:
現有矩陣 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
給定 target = 5,返回 true。
給定 target = 20,返回 false。
解題思路:
Alice: 在二維數組中搜索一個數字是否存在 ?
Bob: 是的,但是數組內部是有序的,從上到下,從左到右遞增。
Alice: 如果 第二行的第一個 要比 第一行的最後一個還要大,整個數組就可以看成一個一維的有序數組了,就可以直接用二分查找了。
Bob: hhh, 我們還是舉個例子吧,沒有例子不直觀。
Alice: 那就假如是在
[[1,2,3],
[2,5,6],
[3,8,9]]
裏面尋找 6 這個元素 ?
Bob: 橫着也有序,縱軸也有序。
Alice: 我明白了,這應該是個雙指針的題目,如果我們能夠找到兩個方向,一個方向數組的值變小,一個方向數組的值變大,那我們就好像站在了一個一維數組的中間位置。
Bob: 一個方向變大,一個方向變小,那就應該是從下到上,從左到右,就是從左下角的位置開始搜索嘍 ?
Alice: 是的,然後每到一個新的位置就再比較一下,最後直到到達最上邊或者最右邊。
Bob: 😎😎,其實從右上角開始搜素也可以的。
代碼:
Python 方法一: 暴力查找:
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
for row in matrix:
for num in row:
if num == target:
return True
return False
Python 方法二: 雙指針
class Solution:
def findNumberIn2DArray(self, matrix: List[List[int]], target: int) -> bool:
if len(matrix) == 0:
return False
x = len(matrix) - 1
y = 0
while x >= 0 and y < len(matrix[0]):
if matrix[x][y] == target:
return True
elif matrix[x][y] < target:
y += 1
else:
x -= 1
return False
Java 方法一: 暴力搜索 + 二分查找:
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
for(int[] array : matrix){
if(binarySearch(array, target) == true){
return true;
}
}
return false;
}
public boolean binarySearch(int[] array, int target){
int l = 0;
int r = array.length - 1;
while(l <= r){
int middle = (l + r) / 2;
if(array[middle] == target){
return true;
}else if(array[middle] < target){
l = middle + 1;
}else{
r = middle - 1;
}
}
return false;
}
}
Java 方法二: 暴力搜索。
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
for(int[] row : matrix){
for(int x : row){
if(x == target){
return true;
}
}
}
return false;
}
}
Java 方法三: 雙指針:
class Solution {
public boolean findNumberIn2DArray(int[][] matrix, int target) {
if(matrix.length == 0){
return false;
}else{
int x = matrix.length - 1;
int y = 0;
while(x >= 0 && y < matrix[0].length){
if(matrix[x][y] == target){
return true;
}else if(matrix[x][y] < target){
y += 1;
}else{
x -= 1;
}
}
return false;
}
}
}
以下爲牛客網平臺代碼
C++ 方法二: 暴力搜索。
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
for(int i=0; i<array.size(); ++i){
for(int j=0; j<array[0].size(); ++j){
if(array[i][j] == target){
return true;
}
}
}
return false;
}
};
JS 方法一: 雙指針。
function Find(target, array)
{
// write code here
var index1 = array.length - 1;
var index2 = 0;
while(index1 >= 0 && index2 < array[0].length){
if(array[index1][index2] == target){
return true;
}else if(array[index1][index2] < target){
index2 ++;
}else{
index1 --;
}
}
return false;
}
JS 方法 一 :還是雙指針,改變搜索的起始位置。
function Find(target, array)
{
// write code here
var index1 = 0;
var index2 = array[0].length - 1;
while(index1 < array.length && index2 >= 0){
if(array[index1][index2] == target){
return true;
}else if(array[index1][index2] < target){
index1 ++;
}else{
index2 --;
}
}
return false;
}
JS 方法二: 暴力查找,O(n^2)
啊,居然也能過。
function Find(target, array)
{
// write code here
for(var i=0; i<array.length; ++i){
for(var j=0; j<array[0].length; ++j){
if(array[i][j] == target){
return true;
}
}
}
return false;
}
易錯點:
長度爲 n
的數組下標的範圍是 [ 0, n-1 ]
總結: