1. Z形打印二维数组
问题描述:
按照Z字型打印二维数组
思路解析:
逐步模拟即可。按照从左到右于从右到左交替打印。分别考虑以下情况:
从左到右打印:当前位于第一行,向右走;当前位于最后一列,向下走
从右到左打印:当前位于第一列,向下打印;当前位于最后一行,向右打印
package 矩阵;
/**
* @author: DreamCode
* @file: Z形打印二维数组.java
* @time: 2022年3月9日-下午4:28:21
*/
public class Z形打印二维数组 {
public static void main(String[] args) {
int[][] matrix = { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16 }};
printZMatrix(matrix);
}
private static void printZMatrix(int[][] matrix) {
// TODO Z形打印二维数组
int r = 0, m = matrix.length - 1;
int c = 0, n = matrix[0].length - 1;
boolean l2r = true; // 是否从左到右
while (r <= m && c <= n) {
if (l2r) {// 从左到右打印
if (r == 0 && c < n) {// 当前位于第一行,向右走
System.out.print(matrix[r][c] + " ");
l2r = !l2r;
c++;
continue;
} else if (c == n && r < m) { // 当前位于最后一列,向下走
System.out.print(matrix[r][c] + " ");
l2r = !l2r;
r++;
continue;
} else {
System.out.print(matrix[r][c] + " ");
r--;
c++;
}
} else { // 从右到左打印
if (c == 0 && r < m) {// 当前位于第一列,向下打印
System.out.print(matrix[r][c] + " ");
l2r = !l2r;
r++;
continue;
} else if (r == m && c < n) {// 当前位于最后一行,向右打印
System.out.print(matrix[r][c] + " ");
l2r = !l2r;
c++;
continue;
} else {
System.out.print(matrix[r][c] + " ");
r++;
c--;
}
}
}
}
}
2. 边界为1的最大方阵
问题描述:
给定一个N×N的矩阵matrix,在这个矩阵中,只有0和1两种值,返回边框全是1的最大正方形的边长长度。
例如:
{0, 1, 1, 1, 1},
{0, 1, 0, 0, 1},
{0, 1, 0, 0, 1},
{0, 1, 1, 1, 1},
{0, 1, 0, 1, 1}
其中,边框全是1的最大正方形的大小是4*4,返回4
思路解析:
暴力枚举。分别枚举每一个正方形的最大边长与左上角的点,判断是否符合要求,始终维护一个最大边长的的正方形。复杂度达到O(n^3)
package 矩阵;
/**
* @author: DreamCode
* @file: 边界为1的最大方阵.java
* @time: 2022年3月9日-下午5:06:55
*/
public class 边界为1的最大方阵 {
public static void main(String[] args) {
int[][] A = new int[][]{
{1, 1, 1, 1},
{1, 0, 1, 1},
{1, 1, 1, 1},
{1, 0, 1, 1},
};
int res = getMaxMatrix(A);
System.out.println(res);
}
private static int getMaxMatrix(int[][] a) {
int n = a.length;
int len = n;
while(n>0) {
for(int i=0;i<=len-n;i++) {
l3:
for(int j=0;j<=len-n;j++) {
//水平检查
int r=i,c=j;
while(c<j+n) {
if(a[r][c++]==0)continue l3;
}
c--;
//右边界检查
while(r<i+n) {
if(a[r++][c]==0)continue l3;
}
r--;
//下边界检查
while(c>=j) {
if(a[r][c--]==0)continue l3;
}
c++;
//左边界检查
while(r>=i) {
if(a[r--][c]==0)continue l3;
}
//走到了最后
return n;
}
}
n--;
}
return 0;
}
}
3. 边界为1的最大方阵_优化
问题描述:
给定一个N×N的矩阵matrix,在这个矩阵中,只有0和1两种值,返回边框全是1的最大正方形的边长长度。
例如:
{0, 1, 1, 1, 1},
{0, 1, 0, 0, 1},
{0, 1, 0, 0, 1},
{0, 1, 1, 1, 1},
{0, 1, 0, 1, 1}
其中,边框全是1的最大正方形的大小是4*4,返回4
思路解析:
提前预处理每一个点,判断该点之下至多含有多少个1,该点之右至多含有多少个1。分别再次枚举每个正方形的最大长度与左上角坐标,判断该点是否满足要求。
package 矩阵;
import java.util.Iterator;
/**
* @author: DreamCode
* @file: 边界为1的最大方阵_优化.java
* @time: 2022年3月9日-下午7:23:35
*/
public class 边界为1的最大方阵_优化 {
static int[][][] rec;
public static void main(String[] args) {
int[][] A = {
{0, 1, 1, 1, 1},
{0, 1, 0, 1, 0},
{0, 1, 1, 1, 1},
{0, 1, 1, 1, 1},
{0, 1, 0, 1, 1}
};
genertateHelpRec(A);
printRec();
int res = getMaxMatrix(A);
System.out.println(res);
}
private static int getMaxMatrix(int[][] a) {
int len = a.length;
int n=len;
while(n>0) { //枚举最大边长
for(int i=0;i<=len-n;i++) { //枚举每个正方形左上角坐标
for(int j=0;j<=len-n;j++) {
if(check(i,j,n)) {
return n;
}
}
}
n--;
}
return 0;
}
private static boolean check(int i, int j, int n) {
if(rec[i][j][0]>=n&&rec[i][j][1]>=n&&rec[i+n-1][j][0]>=n&&rec[i][j+n-1][1]>=n) {
return true;
}
return false;
}
private static void printRec() {
for(int i=0;i<rec.length;i++) {
for(int j=0;j<rec[i].length;j++) {
System.out.print(rec[i][j][0]+","+ rec[i][j][1]+'\t');
}
System.out.println();
}
}
private static void genertateHelpRec(int[][] a) {
// TODO 数据预处理
int n = a.length;
rec = new int[n][n][2];
//处理最后一行n-1
int row = n-1;
for(int i=n-1;i>=0;i--) {
if(a[row][i]==1) { //当前的位置为1
if(i==n-1) { //为最后一个元素
rec[row][i][0]=1;
}else {
rec[row][i][0]=rec[row][i+1][0]+1;
}
rec[row][i][1]=1;
}
}
//处理0-n-2行
for(int i=n-2;i>=0;i--) {
for(int j=n-1;j>=0;j--) {
if(a[i][j]==1) {//当前值为1
if(j==n-1) {//当前为最后一列
rec[i][j][0]=1;
}else {
rec[i][j][0]=rec[i][j+1][0]+1;
}
rec[i][j][1]=rec[i+1][j][1]+1;
}
}
}
}
}
4. 将0所在的行列清零
问题描述:
将二维数组0所在的行和列清为0
思路解析:
模拟遍历。记录出现0的行与列,遍历二维数组,如果当前的行或者列存在0,则赋值为0
package 矩阵;
/**
* @author: DreamCode
* @file: 将0所在的行列清零.java
* @time: 2022年3月9日-下午4:06:28
*/
public class 将0所在的行列清零 {
public static void main(String[] args) {
int[][] matrix = {
{ 1, 2, 3, 4, 100 },
{ 5, 6, 7, 0, 101 },
{ 9, 0, 11, 12, 102 },
{ 13, 14, 15, 16, 103 },
{ 104, 105, 106, 107, 103 }, };
solve(matrix);
printMatrix(matrix);
}
private static void printMatrix(int[][] matrix) {
// TODO 打印二维数组
for(int arr[]: matrix) {
for(int num:arr) {
System.out.print(num+" ");
}
System.out.println();
}
}
private static void solve(int[][] matrix) {
int M = matrix.length;
int N = matrix[0].length;
int[] RecordRow = new int[M];
int[] RecordCol = new int[N];
for(int i=0;i<M;i++) {
for(int j=0;j<N;j++) {
if(matrix[i][j]==0) {
RecordCol[j]=1;
RecordRow[i]=1;
}
}
}
for(int i=0;i<M;i++) {
for(int j=0;j<N;j++) {
if(RecordRow[i]==1||RecordCol[j]==1) {
matrix[i][j]=0;
}
}
}
}
}
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
思路分析:
逐步模拟遍历四个边
package 矩阵;
/**
* @author: DreamCode
* @file: 顺序打印二维数组.java
* @time: 2022年3月9日-下午3:47:40
*/
public class 顺序打印二维数组 {
public static void main(String[] args) {
int[][] arr = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
printMatrix(arr);
}
private static void printMatrix(int[][] arr) {
int LeftUpRow=0,LeftUpCol=0,RightDownRow=arr.length-1,RightDownCol=arr[0].length-1;
while(LeftUpCol<=RightDownCol&&LeftUpRow<=RightDownRow) {
int r=LeftUpCol,c=LeftUpCol;
//上边
while(c<=RightDownCol) {
System.out.print(arr[r][c++]+" ");
}
//复位
c=RightDownCol;
r++;
//右边
while(r<=RightDownRow) {
System.out.print(arr[r++][c]+" ");
}
//复位
r = RightDownRow;
c--;
//下边
while(c>=LeftUpCol) {
System.out.print(arr[r][c--]+" ");
}
//复位
c=LeftUpCol;
r--;
//左边
while(r>LeftUpRow) {
System.out.print(arr[r--][c]+" ");
}
LeftUpCol+=1;
LeftUpRow+=1;
RightDownCol-=1;
RightDownRow-=1;
}
}
}