顺时针打印二维数组:
题目:
顺时针打印二维数组。
例如:将如下数组:
1
2
3
4
5 > {{1, 2, 3, 4},
> {5, 6, 7, 8},
> {9, 10, 11, 12},
> {13, 14, 15, 16}}
>
输出为:1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10
思路:
可以先一圈一圈的打印。先打印外圈,再缩小边界范围循环打印内圈即可。打印的时候注意控制边界。
代码示例:
1 | public class 顺时针打印二维数组 { |
程序运行结果:
1 | 1 2 3 4 8 12 16 15 14 13 9 5 6 7 11 10 |
0所在的行列清零:
题目:
如果矩阵中某个元素为0,则将其所在的行和列清零。
1 2 3 4
5 6 0 8
9 0 11 12
13 14 15 16
思路:
先扫描整个二维数组,开辟两个一维数组,分别标记零所在的行和列。最后,在整个二维数组中,如果发现行或者列被标记,所在的行或者列的数据就清零。
代码示例:
1 | public class 零所在的行和列清零 { |
程序运行结果:
1 | 1 0 0 4 |
Z字形打印矩阵:
题目:
按如下规律,打印出矩阵元素。
思路:
做该题时,可以分解为打印两个方向,从左下角打印到右上角,再从右上角打印到左下角。分别控制好边界的转化方向即可。
代码示例:
1 | public class Z形打印矩阵 { |
程序运行结果:
1 | 1 2 5 9 6 3 4 7 10 11 8 12 |
边界为1的最大子方阵:
题目:
给定一个N * N 的矩阵matrix,这个矩阵中,只有0和1两种值,返回边框全是1的最大正方形的边长长度。
例如:
1
2
3
4
5
6 > {0, 1, 1, 1, 1},
> {0, 1, 0, 0, 1},
> {0, 1, 0, 0, 1},
> {0, 1, 1, 1, 1},
> {1, 1, 0, 1, 1}
>
其中,边框全是1的最大正方形的大小是4*4,返回4.
思路:
本题为基础解法,枚举。下道题该题的优化的解法。
枚举,从n ~ 1 遍历每个正方形的四条边,如果四条边都是1,则返回n。
代码示例:
1 | public class 边界为1的最大子方阵 { |
程序运行结果:
1 | 4 |
边界为1的最大子方阵优化:
思路分析:
上题中的枚举算法时间复杂度为O(n^4), N N N * 4n的时间复杂度。
可以通过优化4n的时间复杂度,将整个解法的时间复杂度降到O(n^3).
思路:预处理方法。
通过预处理方法,先生成一个对应的三维数组,二维平面空间和矩阵大小相等,第三维存储两个元素,第一个数表示,包括自己以及右方连续为1的个数,如果自己为0,则该数为0。第二个数表示,包括自己以及下方连续为1的个数,如果自己为0,则该数为0。通过生成这个辅助表,可以在判断是否是最大方阵的时候大大加快判断速度,可将4个while循环去除,每次只需判断一次即可,判断复杂度变为O(1)。
生成辅助举证举例如下:矩阵为记为A
1
2
3
4
5
6 > {0, 1, 1, 1, 1},
> {0, 1, 0, 0, 1},
> {0, 1, 0, 0, 1},
> {0, 1, 1, 1, 1},
> {1, 1, 0, 1, 1}
>
如以上矩阵可以生成如下辅助数组help:
1
2
3
4
5
6
7
8 > {{0, 0}, {4, 4}, {3, 1}, {2, 1}, {1, 5}},
> {{0, 0}, {1, 4}, {0, 0}, {0, 0}, {1, 4}},
> {{0, 0}, {1, 3}, {0, 0}, {0, 0}, {1, 3}},
> {{0, 0}, {4, 2}, {3, 1}, {2, 2}, {1, 2}},
> {{2, 1}, {1, 1}, {0, 0}, {2, 1}, {1, 1}}
> //注意:生成辅助数组时,因为每个点记录的都是右下方的统计值,所以
> // 必须从右下方开始倒退生成整个辅助数组。
>
当生成如上辅助数组时,每次检查四条边的时候,可以直接检查三个顶点的数字,即可判断是否四条边都是1。例如:当检查n=4时,检查到
A[0][1]
点时,可以直接判断(help[0][1][0] >= n &&help[0][1][1] >= n help[0][1+n][1] >= n help[0+n][1][0] >= n
)如果都成立,即可知四条边上的值为1。此时直接返回n即可。具体代码示例如下:
代码示例:
1 | public class 边界为1的最大子方阵_优化 { |
程序运行结果:
1 | 生成的辅助数组数据如下: |
子数组最大和累加:
题目:
给定一个数组arr,返回子数组的最大累加和。
例如:arr[1, -2, 3, 5, -2, 6, -1];所有的子数组中[3, 5, -2, 6]可以累加出最大和12,所以返回12;
思路:
有两种解法:
方法1 : 暴力法
可以通过暴力法,把所有可能的子数组情况进行累加。最后比较,得出最大值即可。
时间复杂度为:O(n^2);
方法2:递推法:
可以通过扫描一次数组,挨着累加,当累加和出现负数,直接舍弃,证明该段子数量最最大子序列没有贡献。每次累加后,与最大的数比较,如果比最大数大,就替换。详细代码如下:
时间复杂度为:O(n)
代码示例:
1 | public class MaxSubArray { |
程序执行结果:
1 | 31 78 93 99 -64 78 41 35 …… |
子矩阵最大累加和:
题目:
给定一个矩阵matrix,其中的值有正、有负、有0,返回子矩阵的最大累加和。
例如:matrix 为:
1
2
3
4 > -1 -1 -1
> -1 2 2
> -1 -1 -1
>
其中最大累加和的子矩阵为:2 2 ,所以返回4.
思路:
有两种方案:
方案1:暴力法,求出所有可能性。不推荐。
方案2:递推法,同上题。
每行为单位,求出单行的最大子序列和。将多行的值累加为一行的值进行累加。最后求出最大值。
代码示例:
1 | public class MaxSubMatrix { |
程序运行结果:
1 | 4 |