在矩阵中寻找最大正方形连续区域
2016-04-17 16:28
477 查看
在矩阵中寻找最大正方形连续区域
问题描叙
输入一个矩阵M、一个数字k,找出一个最大的正方形连续区域,这个区域里的数字均是k。
界的思考
对于矩阵M中的每一个元素,要么等于k要么不等于k,要知道这个数的状态,必须有一次比较。一共n个数,所以至少需要n2n^2次比较。故比较次数的下界为Ω(n2)\Omega(n^2),那么是否存在一个O(n2)O(n^2)的算法来解决这个问题呢?算法
M中的每一个元素MijM_{ij}都有一个与之对应的数值maxijmax_{ij}记录着以这个元素为左上角顶点的最大的一个正方形连续区域的大小(行/列 数)。对元素MijM_{ij}有两种状态
Mij≠kM_{ij}\ne k , 此时可以得出maxij=0max_{ij}=0。
Mij=kM_{ij} = k , 此时可以得出maxij=min(max(i+1)j,maxi(j+1),max(i+1)(j+1))max_{ij}=min(max_{(i+1)j},max_{i(j+1)},max_{(i+1)(j+1)})。
从右到左,从下往上地扫描矩阵M,计算出每一个元素的maxijmax_{ij},其中最大的maxijmax_{ij}就是矩阵M的最大正方形连续区域的大小,其对应的元素的下标(i,j)就是这块连续区域的左上角顶点。
内存使用
大可不必创建 row×columnrow \times column 个空间来存储每一个元素的maxijmax_{ij},实际上,在比较过程中只用min(row,column)+1min(row,column)+1 个内存空间就行了。过程图示
例图:
第一轮循环:
第二轮循环:
第三轮循环:
用一个数据结构记录当前找到的最大的连续正方形的大小和对应的左上角坐标。
在比较的过程中,如果遇到更大的连续正方形,则更新记录。
代码
< header and helper >#include<iostream> using namespace std; struct max_memo{//记录最大连续正方形区域的大小和左上角的坐标 //左上角的坐标 int row; int col; int num;//大小---以行or列为单位 }; //放回三个数中最小值。 int min(int left, int down, int leftdown){ left = left < down ? left : down; return left < leftdown ? left : leftdown; }
< search >
void search(int M[][5],int k,int row,int col, max_memo &Max_memo){ int *memo = new int[row]; int up_one; int current; for (int i(0); i <row; i++){//初始化最后一行 if (M[col - 1][row - 1 - i] == k) memo[i] = 1; else memo[i] = 0; } Max_memo.col = col - 1, Max_memo.row = row - 1, Max_memo.num = memo[0];//初始化 int ex_index;//记录交换时的下标。 for (int row_local(row - 2), col_local(col - 1); row_local >= 0;)//外循环。 { col_local = (col - 1);//初始化列坐标---每次内循环从最右边开始,向左移动。 if (M[row_local][col_local] == k) { up_one = 1;//计算最右端的元素的最大连续区域(0 or 1) if (up_one > Max_memo.num){ Max_memo.col = col_local, Max_memo.row = row_local, Max_memo.num = up_one;//更新 } } else up_one = 0; col_local--; while (col_local >= 0){//内循环 ex_index = (col - 1) - col_local-1; if (M[row_local][col_local] != k){ current = 0; } if (M[row_local][col_local] == k){ current = min(up_one, memo[ex_index + 1], memo[ex_index]) + 1; if (current > Max_memo.num){ Max_memo.col = col_local, Max_memo.row = row_local, Max_memo.num = current;//更新 } } memo[ex_index] = up_one; up_one = current; col_local--;//向左移 } memo[row - 1] = up_one;//第一轮循环结束。 row_local--;//向上移 } delete[] memo; }
< main >
int main(){ int M[][5] = { /* { 0, 1, 1, 1, 1 }, { 0, 1, 2, 2, 1 }, { 1, 1, 2, 2, 1 }, { 1, 1, 2, 2, 1 }, { 1, 1, 0, 0, 1 } */ {0,0,0,0,1}, {0,0,0,0,1}, {0,0,0,0,1}, {0,0,0,0,1}, {0,0,0,0,0} }; max_memo Max_memo; int k = 1; search(M, k, 5, 5, Max_memo); if (Max_memo.num) cout << "结果: 坐标(" << Max_memo.row << ", " << Max_memo.col << "); 大小(以行为单位): " << Max_memo.num << endl; else cout << "没有值为"<<k<<"的连续正方形区域" << endl; cout << endl; system("pause"); }
相关文章推荐
- mvc+webapi+dapper+ef codefirst项目搭建
- 线性地址到物理地址的映射
- 复制文件
- 数据结构与算法
- Unity3d-Application设备读写目录
- linux基础学习之 gSOAP(1)
- SVM核函数总结
- 第七周学习进度
- 《java并发编程实战》读书笔记二 对象的发布与逸出
- Android 屏幕尺寸、分辨率、像素密度等UI设计参考
- Shell编程基础
- OkHttp深入学习(一)——初探
- C++实现删除单链表节点的功能(源代码+截图)
- Profibus基础知识学习——报文
- 【leetcode】153. Find Minimum in Rotated Sorted Array
- 第8周项目3—指向学生类的指针
- git 和xcode
- Android xml资源文件中@、@android:type、@*、?、@+含义和区别
- SSM框架开发时出现HTTP 400错误
- 第五周项目三(1)-时间类