二维数组返回最大子矩阵之和
设计思路
将二维数组转化为一位数组(并非形式上的转化而是将连续的行合并然后当做上次编写的一维数组求最大子数组和)来计算。时间复杂度没有达到要求的O(n),也是通过遍历的方式将一个子矩阵与上几个子矩阵相加如果小于0则舍去这个子矩阵,按此方法计算从这个子矩阵以后的矩阵,知道遍历完取最大值。
代码:
package soft_third_test; public class test { static int maxSum(int p[][],int startLine,int endLine,int n){ int ans=p[endLine][1]-p[startLine][1]; int cmax=ans; for(int i=2;i<=n;i++){ int ci=p[endLine][i]-p[startLine][i]; cmax=Math.max(cmax+ci, ci); ans=Math.max(cmax, ans); } //System.out.println(startLine+" "+endLine+" "+ans); return ans; } static int[][] colSum(int arr[][]){ int m=arr.length; int n=arr[0].length; int p[][]=new int[m+1][n+1]; for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) p[i][j]=p[i-1][j]+arr[i-1][j-1]; return p; } static int maxArrSum(int arr[][]){ int m=arr.length; int n=arr[0].length; if(m>n){ arr=reverseArr(arr); int tmp=m; m=n; n=tmp; } int p[][]=colSum(arr); int tempMax=0; //h表示当前矩阵的行数,即为把对多少行当做一行看待 for(int h=1;h<=m;h++) for(int i=1;i+h-1<=m;i++){ int endLine=i+h-1; //转换为长度为n的一位数著,复杂度为O(n) tempMax=Math.max(tempMax, maxSum(p,i,endLine,n)); } return tempMax; } static int[][] reverseArr(int[][] arr) { // TODO Auto-generated method stub int m=arr.length; int n=arr[0].length; int newArr[][]=new int[n][m]; for(int i=0;i<m;i++) for(int j=0;j<n;j++) newArr[j][i]=arr[i][j]; return newArr; } public static void main(String[] args) { // TODO Auto-generated method stub int arr[][]={{1,2,-51,-4,-50},{-8,-3,4,255,1},{3,8,104,1,3},{-4,-1,10,7,-6}}; int ans=maxArrSum(arr); //System.out.print("ddd"); System.out.println(ans); } }
结果截图
总结:
总的来说算法颇为复杂,刚开始时候就大概想到与上次一维数组肯定有联系但是始终没有设计思路。通过几天的网上参考,以及跟郭昊同学相互讨论最终写出了这个方法。这次我担任编写程序的部分,感觉很累,但是在完成的时候,我们这个团队(虽然只有两个人)都感觉很兴奋吧。自己感觉我们的水平现在还是一个低水平,不要不好意思跟队友争论,每次思想的碰撞都可能产生一个更加完美的想法,而且结组可以让我们更加完善自己找到自己那些方面有不足之处。同时也要多上网学习,我们现在有网络这个东西不药浪费。另外就是前几次都是用C++编写的JAVA都快忘干净了,应该及时复习那些基础性的东西。
团队照片: