在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
Java
1. 暴力法
直接遍历二维数组,如果存在就返回true。时间复杂度O(n2)。
public class Main {
//暴力法
public boolean find(int target, int[][] array) {
for (int[] arr : array) {
for (int a : arr) {
if (target == a) {
return true;
}
}
}
return false;
}
}
测试结果:
运行时间:181ms 占用内存:17444k
2. 从左下角查找
由于序列具有以下性质:
- 一行都按照从左到右递增的顺序排序
- 每一列都按照从上到下递增的顺序排序
对左下角m来说,是该列最大值,是该行最小值
- 若m==target,返回true
- 若m>target,则row–
- 若m<target,则col++
时间复杂度为:O(rows+cols)
public class Main {
//从左下角比较
public boolean find(int target, int[][] array) {
int rows = array.length;
if (rows == 0) return false;
int cols = array[0].length;
int row = rows - 1;
int col = 0;
while (row >= 0 && col < cols) {
if (array[row][col] > target) row--;
else if (array[row][col] < target) col++;
else return true;
}
return false;
}
}
测试结果:
运行时间:165ms 占用内存:18488k
3.折半查找
从最后一行向上比较确定在那一行,对此行使用折半查找。对m行n列矩阵数组,时间复杂度为O(m+log2n)
public class Main {
public boolean find(int target, int[][] array) {
int rows = array.length;
if (rows == 0) return false;
int cols = array[0].length;
if (cols == 0) return false;
for (int row = rows - 1; row >= 0; row--) {
if (target >= array[row][0] && target <= array[row][cols - 1]) {
if (array[row][0] == target) return true;
if (array[row][cols - 1] == target) return true;
int left = 0, right = cols - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (array[row][mid] == target) return true;
if (array[row][mid] > target) right = mid - 1;
if (array[row][mid] < target) left = mid + 1;
}
break; //查找终止
}
}
return false;
}
}
测试结果:
运行时间:146ms 占用内存:18064k
Kotlin
fun find(target: Int, array: MutableList<MutableList<Int>>): Boolean {
val rows = array.size
if (rows == 0) return false
val cols = array[0].size
if (cols == 0) return false
for (row in 0..<rows) {
if (target >= array[row].first() && target <= array[row].last()) {
//二分查找
if (target == array[row].first() || target == array[row].last()) return true
var left = 0
var right = cols - 1
while (left <= right) {
val mid = (right - left) / 2 + left
array[row][mid].let {
if (it == target) return true
if (it > target) right = mid - 1
else left = mid + 1
}
}
break
}
}
return false
}
Python
def find(target: int, array: [[int]]) -> bool:
rows = len(array)
if rows == 0:
return False
cols = len(array[0])
if cols == 0:
return False
for row in range(rows):
if target >= array[row][0] or target <= array[row][-1]:
if target == array[row][0] or target == array[row][-1]:
return True
left, right = 0, cols - 1
while left <= right:
mid = (right + left) // 2
if array[row][mid] == target:
return True
if array[row][mid] > target:
right = mid - 1
else:
left = mid + 1
break
return False
Rust
fn find(target: i64, array: &Vec<Vec<i64>>) -> bool {
let rows = array.len();
if rows == 0 {
return false;
}
let cols = array[0].len();
if cols == 0 {
return false;
}
for row in 0..rows {
if target >= *array[row].first().unwrap() || target <= *array[row].last().unwrap() {
if target == *array[row].first().unwrap() || target == *array[row].last().unwrap() {
return true;
}
let mut left = 0;
let mut right = cols - 1;
while left <= right {
let mid = (right - left) / 2 + left;
if array[row][mid] == target {
return true;
} else if array[row][mid] > target {
right = mid - 1;
} else {
left = mid + 1;
}
}
break;
}
}
false
}
Go
func find(target int, array [][]int) bool {
rows := len(array)
if rows == 0 {
return false
}
cols := len(array[0])
if cols == 0 {
return false
}
for row := 0; row < rows; row++ {
if target >= array[row][0] && target <= array[row][cols-1] {
if target == array[row][0] || target == array[row][cols-1] {
return true
}
left := 0
right := cols - 1
for left <= right {
mid := (right-left)/2 + left
if array[row][mid] == target {
return true
} else if array[row][mid] > target {
right = mid - 1
} else {
left = mid + 1
}
}
break
}
}
return false
}
C++
#include <vector>
bool find(int target, std::vector<std::vector<int>>& array) {
int rows = array.size();
if (rows == 0) {
return false;
}
int cols = array[0].size();
if (cols == 0) {
return false;
}
for (int row = 0; row < rows; row++) {
if (target >= array[row][0] && target <= array[row][cols - 1]) {
if (target == array[row][0] || target == array[row][cols - 1]) {
return true;
}
// 二分查找
int left = 0;
int right = cols - 1;
while (left <= right) {
int mid = (right - left) / 2 + left;
if (array[row][mid] == target) {
return true;
} else if (array[row][mid] > target) {
right = mid - 1;
} else {
left = mid + 1;
}
}
break;
}
}
return false;
}