行、列递增的二维数组数字查找
来源:互联网 发布:球头铣刀怎么编程 编辑:程序博客网 时间:2024/05/25 08:14
二维数组四分查找
问题:
一个二维数组,但行递增、单列递增,编写程序,在数组中查找某个数字(key),要求时间复杂度小于O(N)。
示例数组
1 3 4
2 4 5
4 5 6
分析:
对这个问题,首先想到的就是二分查找,对一位数组效率最高的查找方法,能不能用类似的方法来处理这个问题呢?
先看一下二分查找
根据mid与key的关系确定下次查找的范围或输出结束
那么二维数组呢
_ 绿色表示比较的数字位置
_ 浅灰色区域表示该区域小于key
_ 深灰色区域表示该区域大于key
_ 浅蓝色表示key可能出现的区域
_ 深蓝色表示下次搜索的区域
中心值大于key的情况与小于时类似
初始代码
(注释见优化后的代码)
#include<stdio.h>void act_search(int a[][3], int key, int left, int right, int top, int bot){ if ((left <= right) && (top <= bot)) { int mid_row = (top + bot) >> 1; int mid_col = (left + right) >> 1; if (a[mid_row][mid_col] != key) { if (a[mid_row][mid_col] > key) { if (a[top][mid_col] >= key) { act_search(a, key, left, mid_col - 1, top, mid_row - 1); if (a[top][mid_col] == key) { printf("a[%d][%d] = %d\n", top, mid_col, a[top][mid_col]); } } else//a[top][mid_col] < key { act_search(a, key, mid_col, right, top, mid_row - 1); } if (a[mid_row][left] >= key) { if (a[top][mid_col] <= key) { act_search(a, key, left, mid_col - 1, top, mid_row - 1); } if (a[mid_row][left] == key) { printf("a[%d][%d] = %d\n", top, mid_col, a[top][mid_col]); } } else//a[mid_row][left]<key { act_search(a, key, left, mid_col - 1, mid_row, bot); } } else //(a[mid_row][mid_col] < key) { if (a[mid_row][right] <= key) { act_search(a, key, mid_col + 1, right, mid_row + 1, bot); if (a[mid_row][bot] == key) { printf("a[%d][%d] = %d\n", mid_col, right, a[mid_col][right]); } } else //a[mid_row][bot] > key { act_search(a, key, mid_col + 1, right, top, mid_row); } if (a[bot][mid_col] <= key) { if (a[mid_row][right] > key) { act_search(a, key, mid_col + 1, right, mid_row + 1, bot); } if (a[bot][mid_col] == key) { printf("a[%d][%d] = %d\n", bot, mid_col, a[bot][mid_col]); } } else //a[bot][mid_col] > key { act_search(a, key, left, mid_col, mid_row + 1, bot); } } } else //a[mid_row][mid_col] != key { printf("a[%d][%d] = %d\n", mid_row, mid_col, a[mid_row][mid_col]); act_search(a, key, left, mid_col - 1, mid_row + 1, bot); act_search(a, key, mid_col + 1, right, top, mid_row - 1); } }}void search(int a[][3], int key, int rol, int cow){ int left = 0; int right = cow - 1; int top = 0; int bot = rol - 1; act_search(a, key, left, right, top, bot);}int main(){ int a[][3]={{ 1, 3, 4 },{2, 4, 5},{4, 5, 6}}; int rol = sizeof(a) / sizeof(a[0]); int cow = sizeof(a[0]) / sizeof(a[0][0]); int key = 4; search(a, key, rol, cow); return 0;}
优化
有一个很大的问题
在函数内部写死了列数让函数局限性变得非常大
而事实上我们知道,二维数组在内存中的存储是连续的,二维数组可以用一维数组来表示和处理,p为首元素指针,COL为二维数组列数,则a[row][col]等价于p[row*COL+col],那么search函数只需接收数组首元素地址而不需接收整个数组,act_search也只需接收首元素地址,另外加列数就好了。然后再将二维数组一维表示就OK了。
#include<stdio.h>void act_search(int *a, int key, int left, int right, int top, int bot, int col){ if ((left <= right) && (top <= bot)) //判别条件,左值不大于右值,顶值不大于底值 { int mid_row = (top + bot) >> 1; //列中心 int mid_col = (left + right) >> 1; //行中心 if (a[mid_row*col+mid_col] != key) //数组中心不等于key { if (a[mid_row*col + mid_col] > key) // 数组中心大于key,排除右下区 { if (a[top*col + mid_col] >= key) //顶行中心大于等于key,排除右上区域,剩余左上区 { act_search(a, key, left, mid_col - 1, top, mid_row - 1, col); 搜索左上区 if (a[top*col + mid_col] == key) //找到key则输出 { printf("a[%d][%d] = %d\n", top, mid_col, a[top*col + mid_col]); } } else //a[top][mid_col] < key //顶行中心小于key,搜索包括所在列的右上区 { act_search(a, key, mid_col, right, top, mid_row - 1, col); } if (a[mid_row*col + left] >= key) //左边中心不小于key,排除左下区 { if (a[top*col + mid_col] <= key) //左上区之前没搜索就搜索 { act_search(a, key, left, mid_col - 1, top, mid_row - 1, col); } if (a[mid_row*col + left] == key) { printf("a[%d][%d] = %d\n", top, mid_col, a[top*col + mid_col]); } } else //a[mid_row][left]<key 排除左上区,搜索包括所在行的左下区 { act_search(a, key, left, mid_col - 1, mid_row, bot, col); } } else //(a[mid_row][mid_col] < key) 中心值小于key,排除左上区 { if (a[mid_row*col + right] <= key) //右边中心值不大于key,排除右上区,检索右下区 { act_search(a, key, mid_col + 1, right, mid_row + 1, bot, col); if (a[mid_row*col + bot] == key) { printf("a[%d][%d] = %d/n", mid_col, right, a[mid_col*col + right]); } } else //a[mid_row][bot] > key 右上区可能有可以,检索 { act_search(a, key, mid_col + 1, right, top, mid_row, col); } if (a[bot*col + mid_col] <= key) // 底行中心值不大于key排除左下区 { if (a[mid_row*col + right] > key) //右下区之前未检索就检索 { act_search(a, key, mid_col + 1, right, mid_row + 1, bot, col); } if (a[bot*col + mid_col] == key) { printf("a[%d][%d] = %d\n", bot, mid_col, a[bot*col + mid_col]); } } else //a[bot][mid_col] > key 左下下区可能存在key { act_search(a, key, left, mid_col, mid_row + 1, bot, col); } } } else //a[mid_row][mid_col] == key 中心值为key,排除左上右下区,搜索不包括所在行列的右上左下区 { printf("a[%d][%d] = %d\n", mid_row, mid_col, a[mid_row*col + mid_col]); act_search(a, key, left, mid_col - 1, mid_row + 1, bot, col); act_search(a, key, mid_col + 1, right, top, mid_row - 1, col); } }}void search(int *a, int key, int rol, int cow){ int left = 0; //左边界列下标 int right = cow - 1; //右边界列下标 int top = 0; //上边界行下标 int bot = rol - 1; //下边界行下标 act_search(a, key, left, right, top, bot, cow); //注意传值列数cow}int main(){ int a[][3] = { { 1, 3, 4 }, { 2, 4, 5 }, { 4, 5, 6 } }; //初始化数组 int rol = sizeof(a) / sizeof(a[0]); //求行数 int cow = sizeof(a[0]) / sizeof(a[0][0]); //求列数 int key = 4; //设要找的数 search(a[0], key, rol, cow); // 传参,搜索 return 0;}
运行结果相同
测试下稍复杂的数组
0 0
- 行、列递增的二维数组数字查找
- 行递增、列递增的二维数组中查找
- 二维数组中查找一个数,该二维数组是 行和列递增的
- 二维递增数组的查找
- 从行,列均为递增的二维数组中查找给定元素
- 二维数组中的查找(行递增矩阵的查找)
- 在一个二维数组中查找一个数,这个数组的行和列都是以递增形式存储的
- 行列递增序列的二维数组查找
- 有一个二维数组杨氏矩阵,数组的每行从左到右是递增的,每列从上到下是递增的,在这样的数组中查找一个数字是否存在
- 有一个二维数组. 数组的每行从左到右是递增的,每列从上到下是递增的. 在这样的数组中查找一个数字是否存在。 时间复杂度小于O(N)
- 有一个二维数组. 数组的每行从左到右是递增的,每列从上到下是递增的. 在这样的数组中查找一个数字是否存在。 时间复杂度小于O(N);
- 有一个二维数组.----杨氏矩阵 数组的每行从左到右是递增的,每列从上到下是递增的. 在这样的数组中查找一个数字是否存在。 时间复杂度小于O(N);
- 杨氏矩阵:有一个二维数组,数组的每行从左到右都是递增的,每列从上到下都是递增的,从这样的数组中查找一个数字是否存在
- //杨氏矩阵 有一个二维数组. 数组的每行从左到右是递增的,每列从上到下是递增的. 在这样的数组中查找一个数字是否存在。
- 在一个每一行从左到右递增每一列从上到下递增的二维数组中查找一个整数是否存在
- 递增二维数组中的查找
- 行元素从小到大递增,列元素从小到大递增的数组查找算法
- 阿里面试算法题-二维递增数组的查找
- 自定义UICollectionView布局
- Pattern类与Matcher方法的验证
- java 基础数据结构
- android camera相关
- Network in Network
- 行、列递增的二维数组数字查找
- 思维导图课程
- 500. Keyboard Row
- Ubuntu修改DNS
- android Vitamio(维他命)入门
- .chm格式的电子书打开是空白的解决办法
- treed树形结构插件应用
- 编译安装caffe
- NYOJ611