lintcode 中等题:Submatrix sum is 0 和为零的子矩阵
给定一个整数矩阵,请找出一个子矩阵,使得其数字之和等于0.输出答案时,请返回左上数字和右下数字的坐标。
给定矩阵
[
[1 ,5 ,7],
[3 ,7 ,-8],
[4 ,-8 ,9],
]
返回 [(1,1), (2,2)]
O(n3) 时间复杂度
解题
直接暴露求解,时间复杂度O(N2*M2 )
public class Solution {
/**
* @param matrix an integer matrix
* @return the coordinate of the left-up and right-down number
*/
public int[][] submatrixSum(int[][] matrix) {
// Write your code here
int[][] res = new int[2][2];
int row = matrix.length;
if(row ==0){
return res;
}
int col = matrix[0].length;
if(col ==0){
return res;
}
for(int i = 0;i< row ;i++){
for(int j = 0;j<col;j++){
int sum = matrix[i][j];
res[0][0]=i;
res[0][1]=j;
for(int n=i+1;n<row;n++){
for(int m=j+1;m<col;m++){
sum+=matrix[n][m];
if(sum==0){
res[1][0] = n;
res[1][1] = m;
break;
}
}
}
}
}
return res;
}
}
Java Code
总耗时: 8203 ms
在编程之美上,看到下面的方法:
1.先去(0,0)到(i,j)内的子矩阵的部分和,和存放中点(i,j)
2.根据上面的子矩阵,求解任意两点和为0的子矩阵
如何求解(0,0)到(i,j)内的子矩阵之和
| (i-1,j-1) | (i-1,j) |
| (i,j-1) | (i,j) |
如上图的子矩阵和的矩阵PS
PS[i-1][j-1] PS[i-1][j] PS[i][j-1]是已经求出的子矩阵的和
显然我们知道PS[i][j-1] = PS[i-1][j-1] + A[i][j-1] 这里的A是原始要求的矩阵,A[i][j-1]也就是(i,j-1)点的值
同理:PS[i-1][j] = PS[i-1][j-1] + A[i-1][j]
很显然:PS[i][j] = PS[i-1][j-1] + A[i-1][j] + A[i][j-1] + A[i][j]
将上面的含有A矩阵元素的值消掉就得到下面的矩阵:
PS[i][j] = PS[i][j-1] + PS[i-1][j] - PS[i-1][j-1]
对于第0行和第0类,我单独处理的
PS[0][0] = A[0][0]
第0行:PS[0][j] =PS[0][j-1] + A[0][j]
第0列:PS[i][0] =PS[i-1][0] + A[i][0]
非0行非0列按照上面的迭代求解
在求解任意两点和为0的子矩阵
我们求的是(i,j)到(m,n)的子矩阵
当m 或者n其中一个为0的时候单独考虑
其他情况 m、n都是非0的时候
要考虑 i、j是否是0的情况
如下:
int sum = 0;
if(i==0 && j==0){
sum = PS[m][n];
}else if(i==0 && j!=0){
sum = PS[m][n] - PS[m][j-1];
}else if(i!=0 && j==0){
sum = PS[m][n] -PS[i-1][n];
}else{
sum = PS[m][n] - PS[i-1][n] - PS[m][j-1] + PS[i-1][j-1];
}
这样计算的最终时间复杂度还是O(N2*M2)
最终程序
public class Solution {
/**
* @param matrix an integer matrix
* @return the coordinate of the left-up and right-down number
*/
public int[][] submatrixSum(int[][] matrix) {
// Write your code here
int[][] res = new int[2][2];
int row = matrix.length;
if(row ==0){
return res;
}
int col = matrix[0].length;
if(col ==0){
return res;
}
// 求解0 0 到i j的部分和
int PS[][] = new int[row][col];
PS[0][0] = matrix[0][0];
for(int i =1;i<row ;i++)
PS[i][0] =PS[i-1][0] + matrix[i][0];
for(int j =1;j<col ;j++)
PS[0][j] =PS[0][j-1] + matrix[0][j];
for(int i =1;i< row;i++){
for(int j=1;j<col;j++){
PS[i][j] = PS[i-1][j] + PS[i][j-1] - PS[i-1][j-1] + matrix[i][j];
}
}
// for(int i =0;i< row;i++){
// for(int j=0;j<col;j++){
// System.out.print(PS[i][j] +" ");
// }
// System.out.println();
// }
//对第0行和第0列单独判断
// 寻找i j 到 m n和为0的数组时间复杂度O(n*n*m*m)
//对第0行和第0列单独判断
// 第0列
for(int i =0;i< row ;i++){
res[0][0] = i;
res[0][1] = 0;
for(int j= i+1;j< row;j++){
if(i==0){
if(PS[j][0]==0){
res[1][0] = j;
res[1][1] = 0;
return res;
}
}
else if(PS[j][0]-PS[i-1][0] ==0){
res[1][0] = j;
res[1][1] = 0;
return res;
}
}
}
// 第0 行
for(int i =0;i< col ;i++){
res[0][0] = 0;
res[0][1] = i;
for(int j= i+1;j< col;j++){
if(i==0){
if(PS[0][j]==0){
res[1][0] = 0;
res[1][1] = j;
return res;
}
}
else if(PS[0][j]-PS[0][i-1] ==0){
res[1][0] = 0;
res[1][1] = j;
return res;
}
}
}
for(int i =0;i<row ;i++){
for(int j=0;j<col;j++){
res[0][0] = i;
res[0][1] = j;
for(int m = i+1;m<row; m++){
for(int n = j+1;n<col;n++){
int sum = 0;
if(i==0 && j==0){
sum = PS[m][n];
}else if(i==0 && j!=0){
sum = PS[m][n] - PS[m][j-1];
}else if(i!=0 && j==0){
sum = PS[m][n] -PS[i-1][n];
}else{
sum = PS[m][n] - PS[i-1][n] - PS[m][j-1] + PS[i-1][j-1];
}
if(sum==0){
res[1][0] = m;
res[1][1] = n;
return res;
}
}
}
}
}
return res;
}
}
Java Code
总耗时: 7060 ms
上面参考的是编程之美
在九章的程序中,PS矩阵行列比原始的矩阵行列多1,在边界出来上不用那么复杂
同时在PS矩阵中求解任意两点的子矩阵时候,利用HashMap,对PS矩阵中任意两点的差值判断是否在HashMap中,当存在的时候就是答案了
public class Solution {
/**
* @param matrix an integer matrix
* @return the coordinate of the left-up and right-down number
*/
public int[][] submatrixSum(int[][] matrix) {
int[][] result = new int[2][2];
int M = matrix.length;
if (M == 0) return result;
int N = matrix[0].length;
if (N == 0) return result;
// pre-compute: sum[i][j] = sum of submatrix [(0, 0), (i, j)]
int[][] sum = new int[M+1][N+1];
for (int j=0; j<=N; ++j) sum[0][j] = 0;
for (int i=1; i<=M; ++i) sum[i][0] = 0;
for (int i=0; i<M; ++i) {
for (int j=0; j<N; ++j)
sum[i+1][j+1] = matrix[i][j] + sum[i+1][j] + sum[i][j+1] - sum[i][j];
}
for (int l=0; l<M; ++l) {
for (int h=l+1; h<=M; ++h) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (int j=0; j<=N; ++j) {
int diff = sum[h][j] - sum[l][j];
if (map.containsKey(diff)) {
int k = map.get(diff);
result[0][0] = l; result[0][1] = k;
result[1][0] = h-1; result[1][1] = j-1;
return result;
} else {
map.put(diff, j);
}
}
}
}
return result;
}
}
Java Code
lintcode 中等题:Submatrix sum is 0 和为零的子矩阵的更多相关文章
- lintcode 中等题:k Sum ii k数和 II
题目: k数和 II 给定n个不同的正整数,整数k(1<= k <= n)以及一个目标数字. 在这n个数里面找出K个数,使得这K个数的和等于目标数字,你需要找出所有满足要求的方案. 样例 ...
- lintcode 中等题:A + B Problem A + B 问题
题目: 中等 A + B 问题 给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符. 如果 a=1 并且 b=2,返回3 注意 你不需要从输入流读入数据,只需要根据aplusb的两个参数 ...
- lintcode 中等题:partition array 数组划分
题目 数组划分 给出一个整数数组nums和一个整数k.划分数组(即移动数组nums中的元素),使得: 所有小于k的元素移到左边 所有大于等于k的元素移到右边 返回数组划分的位置,即数组中第一个位置i, ...
- lintcode 中等题:permutations II 重复数据的全排列
题目 带重复元素的排列 给出一个具有重复数字的列表,找出列表所有不同的排列. 样例 给出列表 [1,2,2],不同的排列有: [ [1,2,2], [2,1,2], [2,2,1] ] 挑战 使用递归 ...
- lintcode 中等题:permutations 全排列
题目 全排列 给定一个数字列表,返回其所有可能的排列. 您在真实的面试中是否遇到过这个题? Yes 样例 给出一个列表[1,2,3],其全排列为: [ [1,2,3], [1,3,2], [2,1,3 ...
- lintcode 中等题:Divide Two Integers 两个数的除法
题目 两个整数相除 将两个整数相除,要求不使用乘法.除法和 mod 运算符. 如果溢出,返回 2147483647 . 样例 给定被除数 = 100 ,除数 = 9,返回 11 解题 15%的通过率 ...
- lintcode 中等题:和大于S的最小子数组
题目 和大于S的最小子数组 给定一个由 n 个整数组成的数组和一个正整数 s ,请找出该数组中满足其和 ≥ s 的最小长度子数组.如果无解,则返回 -1. 样例 给定数组 [2,3,1,2,4,3] ...
- lintcode 中等题:find the missing number 寻找缺失的数
题目 寻找缺失的数 给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数. 样例 N = 4 且序列为 [0, 1, 3] 时,缺失的数为2. 注意 可以改变序 ...
- lintcode 中等题: Implement Trie
题目 Implement Trie Implement a trie with insert, search, and startsWith methods. 样例 注意 You may assu ...
随机推荐
- 工作案件1 一切都是有check引起的
HTML中input标签有两个类型,radio和checkbox,一个单选按钮一个复选按钮.jquery可以通过$(":radio")和$(":checkbox" ...
- Winform 导出Excel
private void 导出excelToolStripMenuItem_Click(object sender, EventArgs e) { ) { var saveFileDialog1 = ...
- SequoiaDB 1.5 版本发布
SequoiaDB 1.5 – 2013.11.13 新特性 1. 新增聚合特性,API实现 GROUPBY, MAX 等功能: 2. 全新改版的Web管理界面: 3. 提供C#语言 ...
- Translation001——android
请尊重原创,转载请注明出处: Author:KillerLegend Link:http://www.cnblogs.com/killerlegend/ BEGIN****************** ...
- ADO.NET的五个主要对象
优秀文章链接:http://www.cnblogs.com/xianspace/archive/2009/02/21/1395307.html http://www.cnblogs.com/aito/ ...
- 试图使用未在此报表服务器中注册或此版 Reporting Services 不支持的数据扩展插件“Devart.Data.PostgreSql”
数据源用的是Postgresql 我在Deploy Report的时候出现这条ErrorMessage Error 2 试图使用未在此报表服务器中注册或此版 Reporting Services 不支 ...
- UserLogin
DAL: IUserDAL namespace Dal { /// <summary> /// This interface is defined for user functions. ...
- CP="CAO PSA OUR" 用P3P header解决iframe跨域访问cookie
1.IE浏览器iframe跨域丢失Session问题 在开发中,我们经常会遇到使用Frame来工作,而且有时是为了跟其他网站集成,应用到多域的情况下,而Iframe是不能保存Session的因此,网上 ...
- 【转】HTTP-only Cookie 脚本获取JSESSIONID的方法
彻底避免xss攻击的方法. 别人可以通过注入js脚本获取你的session cookie,如果幸运的话还可以获取通过js遍历你的dom树获取你的用户的用户名和密码. 如果只是通过正则表达式验证输入的话 ...
- 2208: [Jsoi2010]连通数 - BZOJ
Description Input 输入数据第一行是图顶点的数量,一个正整数N. 接下来N行,每行N个字符.第i行第j列的1表示顶点i到j有边,0则表示无边. Output 输出一行一个整数,表示该图 ...