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 ...
随机推荐
- float闭合(清除浮动)和CSS HACK
一.float 闭合(清除浮动) 将以下代码加入Global CSS 中,给需要闭合的div加上 class="clearfix" 即可,屡试不爽. <style>.c ...
- 运行yum报错Error: Cannot retrieve metalink for repository: epel. Please verify its path and try again
今天给Centos通过rpm -Uvh装了个epel的扩展后,执行yum就开始报错: Error: Cannot retrieve metalink for repository: epel. Ple ...
- silverlight视频、音频
几天发现MediaElement播放不了wav格式的音频文件,在网上找到一篇解决的文章: http://www.cnblogs.com/rupeng/archive/2011/02/20/195936 ...
- mongodb的常用操作
对于nosql之前工作中有用到bekerlydb,最近开始了解mongodb,先简单写下mongodb的一些常用操作,当是个总结: 1.mongodb使用数据库(database)和集合(collec ...
- aspx返回json数据
JQuery.getJSON 从aspx页面返回JSON数据 . -- ::| 分类: asp.net |举报|字号 订阅 . 发送请求的WebForm1.aspx <%@ Page Langu ...
- SQL中的日期时间函数
之所以把日期时间函数单独拿出来回顾一下,是因为这一部分的内容比较独立,C#中也有类似的日期时间函数,趁着想得起来,写个标题先.
- gcc链接程序时出现undefined reference to""错误
如:: undefined reference to ‘mq_unlink',意思是指函数mq_unlink没有定义. 可以使用如下步骤找到该函数所在的库: 1).查找哪些库包含了或使用了该函数:gr ...
- Tools for Presention
ZoomIt v4.5 http://technet.microsoft.com/en-us/sysinternals/bb897434.aspx 微软的教师演示工具 主要有放大,画图,倒计时的功能. ...
- 关于一道简单的Java 基础面试题的剖析: short s1=1;s1 = s1 +1会报错吗?
package common; public class ShortTypeTest { /* * @param args */ public static void main(String[] ar ...
- 删除或清空具有外键约束的表数据报-ERROR 1701 (42000)
OS: centos 6.3 DB:5.5.14 mysql> select database();+------------+| database() |+------------+| sa ...