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 ...
随机推荐
- javascript中for-in的用法
for(var 变量名 in object) alert(变量名[第n个]) : 如果object是josn对象的话,变量名就是属性名 如果object是数组的话,变量名就是数字下标 例子:JOSN对 ...
- Hbase 0.98集群搭建的详细步骤
准备工作 Hbase的搭建是依赖于Hadoop的,Hbase的数据文件实际上存储在HDFS文件系统中,所以我们需要先搭建hadoop环境,之前的博文中已经搭建过了(详见http://www.cnblo ...
- protobuf编译报错
在下载protobuf进行编译的时候会出现如图所示的错误 修改 C:\protobuf-2.4.1\gtest\include\gtest\internal\gtest-tuple.h(C:是我解压p ...
- vmware虚拟机上网:host-only
host-only配置 首先主机:vmware1要能共享本地连接这个网络,共享后vmware的ip会自动设置为如图 其次,vmware网络设置如图 最后,虚拟机设置如图 这样,主机与虚拟机之间就能pi ...
- RichTextBox 自动滚动到最后
RichTextBox.AppendText($"[{DateTime.Now.ToString("hh:mm:ss")}] {msg}\n"); RichTe ...
- Android屏幕像素密度适配详解
讲到像素密度,我们先要搞明白什么是像素密度,像素密度的字面上的意思为手机屏幕上一定尺寸区域内像素的个数.在Android开发中, 我们一般会使用每英寸像素密度(dpi)这样一个单位来表示手机屏幕的像素 ...
- Java从入门到精通——数据库篇之JAVA中的对Oracle数据库操作
在Java中对Oracle数据库的操作分为两种:一.查询.二.非查询. 下面是我对其进行总结: 一.查询数据 /** * 根据用户代码查询 * @param userId * @return 如果存在 ...
- 从零单排学JavaWeb
之前是一个asp爱好者,感觉前途渺茫,特此转向Powerful的Java阵型,寻求心灵上的慰藉. 把自己遇到的问题记录下来,同时也分享给大家. 环境-下载 1 JDK http://dlsw.bai ...
- [Android Training视频系列] 8.1 Controlling Your App’s Volume and Playback
主要内容:1 鉴别使用的是哪个音频流2 使用物理音量键控制应用程序的音量 3 使用物理播放控制键来控制应用程序的音频播放 视频讲解:http://www.eyeandroid.com/thread-1 ...
- HTTP 错误 500.21 - Internal Server ErrorHTTP
应用程序“DEFAULT WEB SITE/WINDRP_TB/TBFXWS”中的服务器错误Internet Information Services 7.5错误摘要HTTP 错误 500.21 - ...