Question
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
关键词:数组 有序 二分查找
Solution
1、暴力破解
时间复杂度:O(N^N)
空间复杂度:O(1)
- Python
# array 二维列表
# target 目标值
def Find(self, target, array):
if len(array)==0 or len(array[0])==0:
return False
for i in range(len(array)):
for j in range(len(array[0])):
if array[i][j] == target:
return True
return False
- C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
if(row==0||col==0)
return false;
int i, j;
for(i=0; i<row; i++){
for(j=0; j<col; j++){
if (target==array[i][j])
return true;
};
};
return false;
};
2、二分查找
a、逐行二分查找
时间复杂度:O(NlogN)
空间复杂度:O(1)
- Python
# array 二维列表
# target 目标值
def Find(self, target, array):
if len(array)==0 or len(array[0])==0:
return False
for i in range(len(array)):
left = 0
right = len(array[0]) - 1
while(left <= right):
j = (left + right) // 2
if target == array[i][j]:
return True
if target > array[i][j]:
left = j + 1
else :
right = j - 1
return False
- C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
if(row==0||col==0)
return false;
int i, j;
int left, right;
for(i=0; i<row; i++){
for(left = 0, right = col-1; left <= right;){
j = (left + right) / 2;
if (target==array[i][j])
return true;
if (target > array[i][j]){
left = j+1;
continue;
};
if (target < array[i][j]){
right = j-1;
continue;
};
};
};
return false;
};
b、二维折半查找
时间复杂度:O(NlogN)
空间复杂度:O(1)
- Python
# array 二维列表
# target 目标值
def Find(self, target, array):
if len(array)==0 or len(array[0])==0:
return False
top = left = 0
bottom = len(array) - 1
right = len(array[0]) - 1
while(top<bottom or left<right):
# 第一行缩小右边界
rleft, rright = left, right
while (rleft<=rright):
j = (rleft + rright) // 2
if array[top][j] == target:
return True
elif array[top][j] > target:
rright = j - 1
else:
rleft = j + 1
right = min(j, right)
top += 1
#最后一行缩小左边界
rleft, rright = left, right
while (rleft<=rright):
j = (rleft + rright) // 2
if array[bottom][j] == target:
return True
elif array[bottom][j] > target:
rright = j - 1
else:
rleft = j + 1
left = max(j, left)
bottom -= 1
#最左列缩小下边界
ctop, cbottom = top, bottom
while (ctop<=cbottom):
i = (ctop + cbottom) // 2
if array[i][left] == target:
return True
elif array[i][left] > target:
cbottom = i - 1
else:
ctop = i + 1
bottom = min(i, bottom)
left += 1
#最右列缩小上边界
ctop, cbottom = top, bottom
while (ctop<=cbottom):
i = (ctop + cbottom) // 2
if array[i][right] == target:
return True
elif array[i][right] > target:
cbottom = i - 1
else:
ctop = i + 1
top = max(i, top)
right -= 1
top = min(len(array)-1, top)
left = min(len(array[0])-1, left)
return array[top][left] == target
- C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
if(row==0||col==0)
return false;
int top = 0;
int left = 0;
int bottom = row - 1;
int right = col - 1;
int rleft, rright, ctop, cbottom;
int i, j;
for(;top<bottom || left<right;){
// 第一行缩小右边界
rleft = left;
rright = right;
while (rleft<=rright){
j = (rleft + rright) / 2;
if (array[top][j] == target)
return true;
else if (array[top][j] > target)
rright = j - 1;
else
rleft = j + 1;
};
if (j < right)
right = j;
top++;
// 最后一行缩小左边界
rleft = left;
rright = right;
while (rleft<=rright){
j = (rleft + rright) / 2;
if (array[bottom][j] == target)
return true;
else if (array[bottom][j] > target)
rright = j - 1;
else
rleft = j + 1;
};
if (j > left)
left = j;
bottom--;
// 最左列缩小下边界
ctop = top;
cbottom = bottom;
while (ctop<=cbottom){
i = (ctop + cbottom) / 2;
if (array[i][left] == target)
return true;
else if (array[i][left] > target)
cbottom = i - 1;
else
ctop = i + 1;
};
if (i < bottom)
bottom = i;
left++;
// 最右列缩小上边界
ctop = top;
cbottom = bottom;
while (ctop<=cbottom){
i = (ctop + cbottom) / 2;
if (array[i][right] == target)
return true;
else if (array[i][right] > target)
cbottom = i - 1;
else
ctop = i + 1;
};
if (i > top)
top = i;
right--;
};
if (top> row - 1)
top = row - 1;
if (left > col - 1)
left = col - 1;
return array[top][left] == target;
};
c、中心二分查找
时间复杂度:O(logN^2)
空间复杂度:O(1)
- Python
# array 二维列表
# target 目标值
def Find(self, target, array):
if len(array)==0 or len(array[0])==0:
return False
def search(top, bottom, left,right):
if top>bottom or left>right:
return False
if top==bottom and left==right:
return (array[top][left]==target)
i = (top + bottom) // 2
j = (left + right) // 2
flag = False
if array[i][j] == target or array[top][left] == target:
return True
# target小于中心点
if array[i][j] > target:
# 上方区域
if target == array[top][left] or target == array[i-1][right]:
return True
elif array[top][left]<target and array[i-1][right]>target:
flag = search(top, i-1, left, right)
#左下区域
if not flag:
if target == array[i][left] or target == array[bottom][j-1]:
return True
elif array[i][left]<target and array[bottom][j-1]>target:
flag = search(i, bottom, left, j-1)
return flag
# target大于中心点
else:
# 右上区域
if target == array[top][j+1] or target == array[i][right]:
return True
elif array[top][j+1]<target and array[i][right]>target:
flag = search(top, i, j+1, right)
#下方区域
if not flag:
if target == array[i+1][left] or target == array[bottom][right]:
return True
elif array[i+1][left]<target and array[bottom][right]>target:
flag = search(i+1, bottom, left, right)
return flag
return search(0, len(array)-1, 0, len(array[0])-1)
- C++
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
if(row==0||col==0)
return false;
return search( array, target, 0, 0, col-1, row-1);
};
bool search(vector<vector<int> > &datas, int target, int left, int top, int right, int bottom){
if (top == bottom && left == right)
return datas[top][left] == target;
else if (datas[top][left]>target || datas[bottom][right]<target)
return false;
else {
int cHoriz = (left + right) / 2;
int cVertic = (top + bottom) / 2;
if (datas[cVertic][cHoriz] == target)
return true;
else {
// 目标大于分割点则排除左上区域,对右下进行递归
if (datas[cVertic][cHoriz] < target) {
if (cHoriz<right && cVertic<bottom &&
search(datas, target, cHoriz+1, cVertic+1, right, bottom))
return true;
}
// 否则排除右下区域,对左上进行递归
else if ((left<cHoriz || top<cVertic) &&
search(datas, target, left, top, cHoriz, cVertic))
return true;
// 对右上区域进行递归
if (cHoriz < right &&
search(datas, target, cHoriz+1, top, right, cVertic))
return true;
// 对左下区域进行递归
if (cVertic < bottom &&
search(datas, target, left, cVertic+1, cHoriz, bottom))
return true;
return false;
}
}
};
3、左下/右上移动元素
从左下角开始,若目标大于当前值,目标区域为当前值右边区域;若小于当前值,目标区域为上方区域。
时间复杂度:O(N)
空间复杂度:O(1)
- Python
## 左下开始移动
# array 二维列表
# target 目标值
def Find(target, array):
if len(array)==0 or len(array[0])==0:
return False
i = len(array)-1
j = 0
while i>=0 and j<len(array[0]):
if target == array[i][j]:
return True
elif target > array[i][j]:
j += 1
else:
i -= 1
return False
- C++
// 左下开始移动
// array 二维列表
// target 目标值
bool Find(int target, vector<vector<int> > array) {
int row = array.size();
int col = array[0].size();
if (row == 0 || col == 0)
return false;
int i, j;
for(i = row-1, j = 0; i>=0 && j < col;){
if(target == array[i][j])
return true;
if(target > array[i][j]){
j++;
continue;
}
if(target < array[i][j]){
i--;
continue;
}
};
return false;
};
转载:https://blog.csdn.net/weixin_44225792/article/details/102112070
查看评论