求一个矩阵中最大的二维子矩阵(元素和最大)
题目:
求一个矩阵中最大的二维子矩阵(元素和最大).如:
1 2 0 3 4
2 3 4 5 1
1 1 5 3 0
中最大的是:
4 5
5 3
要求:(1)写出算法;(2)分析时间复杂度;(3)用C写出关键代码
分析:方法一、这是最容易想到也是最容易实现的方法。遍历矩阵(行迭代器为i,列迭代器为j),以当前遍历到的元素为首a[i,j],计算二维子矩阵的和(sum=a[i,j]+a[i+1,j]+a[i,j+1]+a[i+1,j+1]),并找出和最大的二维矩阵,注意矩阵的最后一行和最后一列不用遍历。时间复杂度为O(i*j)。
实现代码:
#include <iostream> using namespace std; void GetMax2Matrix(int arr[][5], int row, int col, int result[][2]) { int max_i = 0; int max_j = 0; int max_sum = -(1<<31); for(int i = 0; i < row-1; i++) for(int j = 0; j < col-1; j++) { int sum = arr[i][j] + arr[i+1][j] + arr[i][j+1] + arr[i+1][j+1]; if(sum > max_sum) { max_sum = sum; max_i = i; max_j = j; } } result[0][0] = arr[max_i][max_j]; result[0][1] = arr[max_i][max_j+1]; result[1][0] = arr[max_i+1][max_j]; result[1][1] = arr[max_i+1][max_j+1]; } int main(void) { int arr[][5] = {1,2,0,3,4, 2,3,4,5,1, 1,1,5,3,0}; int result[2][2]; GetMax2Matrix(arr, 3, 5, result); for(int i = 0; i<2; i++) for(int j = 0; j < 2; j++) cout<<result[i][j]<<'\t'; cout<<endl; return 0; }
方法二、这是对方法一的改进。分析方法一可知,方法一在每次遍历中,必须同时访问四个元素(a[i,j],a[i+1,j],a[i,j+1],a[i+1,j+1]),方法一的遍历效果如图所示(用方框框住的表示当前访问到或已访问的元素,元素被框住的次数就越多,表示被访问的次数也就越多,被染的颜色也就越深)。

可从图中看出,方法一中多个元素被重复访问多次,要知道访问一次元素的代价是不容小视的。实际上我们是可以对其进行改进,使每个元素的访问次数尽可能的降低的。改进方法如下:
一、增加一个变量,last_vsum(叫做“最新纵向和”,v是vertical) 且初始化为last_vsum = a[0,0]+a[1,0],其作用将在下面说明。
二、改变遍历方式,原先每次访问四个元素,现在变为每次访问纵向的两个元素(a[i,j],a[i+1,j]),横向遍历,遍历的起始点改为第二个元素,终点到最后一个元素。
三、改变求和方式,求和方法是:首先将上一次保存的和last_vsum加进sum中,再将last_vsum更新为当前纵向的两个元素a[i,j],a[i+1,j]之和,然后再将last_vsum加入sum中,这样就得到本次二维矩阵的和可与maxsum进行比较。如此每次求和只需访问两个元素a[i,j],a[i+1,j]。
方法二执行步骤与效果图:

实现代码:
void GetMax2Matrix2(int arr[][5], int row, int col, int result[][2]) { int max_i = 0; int max_j = 0; int max_sum = -(1<<31); for(int i = 0; i < row-1; i++) { int last_sum = arr[i][0] + arr[i+1][0];//每行开始时,初始化last_sum为第一的和,然后从第二列开始 for(int j = 1; j < col; j++) { int sum = last_sum; last_sum = arr[i][j] + arr[i+1][j];; sum += last_sum; if(sum > max_sum) { max_sum = sum; max_i = i; max_j = j; } } } result[0][0] = arr[max_i][max_j]; result[0][1] = arr[max_i][max_j+1]; result[1][0] = arr[max_i+1][max_j]; result[1][1] = arr[max_i+1][max_j+1]; }

浙公网安备 33010602011771号