杨氏矩阵
有一个二维数组. 数组的每行从左到右是递增的,每列从上到下是递增的,在这样的数组中查找一个数字是否存在。 要求:时间复杂度小于O(N)
例如:
每一行逐个增大,每一列也逐个增大。
现要求在杨氏矩阵中找一个数 k ,要求为:时间复杂度小于O(N)。
(在一个N个元素的二维数组中查找一个元素,最坏的情况是查找N次,时间复杂度为O(N))
这样子就不能在数组中逐个查找。
解析
现创建一个数组符合杨氏矩阵,arr[3][3]= {1, 2, 3, 4, 5, 6, 7, 8, 9};
可观察数组右上角的元素的特点:为一行中最大的元素,为一列中最小的元素。
当要查找的元素k > arr[j][i]时,说明 k 不在第 j 行,从第 j + 1 行开始找;当 k < arr[ j ][ i ]时, 说明 k 不在 i 列,从第 i - 1列开始找。
假设要查找的元素为k = 7;则从数组右上角开始找。
因为k = 7 > arr[0][2] = 3, 所以 k 不在第0行。
因为 k = 7 > arr[1][2] = 6, 所以 k 不在第1行。
因为 k = 7 < arr[2][2] = 9, 所以 k 不在第 2 列。
因为 k = 7 < arr[2][1] = 8, 所以 k 不在第 1 列。
最后 k = 7 = arr[2][0] = 7
代码
先写出主函数
int main()
{
int arr[3][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // 创建杨氏矩阵 arr数组
int ret = FindRound(arr, 3, 3, 7); //找到了返回1, 没找到返回0
printf("%d\n", ret); //打印结果
return 0;
}
再写FindRound()
//x、y为下标,key为要找的元素
int FindRound(int arr[][3], int x, int y, int key)
{ }
从arr[0][2]开始找
int FindRound(int arr[][3], int x, int y, int key)
{
int i = 0;
int j = y - 1;
while (i < x && j >= 0) //当数组越界时,, 跳出循环
{
}
return 0; //找不到时返回0
}
逐行/列查找
//x、y为下标,key为要找的元素
int FindRound(int arr[][3], int x, int y, int key)
{
int i = 0;
int j = y - 1;
while (i < x && j >= 0) //当数组越界时,, 跳出循环
{
if (arr[i][j] < key) //跳到下一行查找
i++;
else if (arr[i][j] > key) //跳到上一列查找
j--;
else
{
printf("arr[%d][%d] = %d\n", i, j, key); //找到了打印元素
return 1; //找到了返回1
}
}
return 0; //找不到时返回0
}
运行
k = 7 找到
k = 11 没找到