4. 多维数组基础题
4.1 顺时针打印二维数组
题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
[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
思路:一圈一圈的打印。
import java.util.ArrayList;
import java.util.Arrays;
public class 顺时针打印2维数组 {
public static void main(String[] args) {
int[][] martix = {{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
};
// for(int[] i:martix) {
// System.out.println(Arrays.toString(i));
// }
System.out.println(Arrays.toString(print(martix)));
}
public static int[] print(int[][] martix) {
int leftUpRow = 0; //行标初始值
int leftUpCol = 0; //列标初始值
int rightDownRow = martix.length -1; //行数
int rightDownCol = martix[0].length - 1; //列数
ArrayList<Integer> list = new ArrayList<Integer>();
while (leftUpCol<rightDownCol && leftUpRow<rightDownRow) {
int r = leftUpRow;
int c=leftUpCol;
while (c <= rightDownCol) {
//上面一条边
list.add(martix[r][c++]);
}
//回复
c = rightDownCol;
r++;
//右面一条边
while (r <= rightDownRow) {
list.add(martix[r++][c]);
}
//恢复
r = rightDownRow;
c--;
while (c >= leftUpCol) {
list.add(martix[r][c--]);
}
//恢复
r--;
c = leftUpCol;
while (r > leftUpRow) {
list.add(martix[r--][c]);
}
//到小一维的数组
leftUpCol++;
leftUpRow++;
rightDownCol--;
rightDownRow--;
}
int[] arr = new int[list.size()];
for(int i=0;i<list.size();i++) {
arr[i] = list.get(i);
}
return arr;
}
}
4.2 0所在的行列清零
题目:编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
输入:
[[1,1,1],
[1,0,1],
[1,1,1]]
输出:
[[1,0,1],
[0,0,0],
[1,0,1]]
public static void setZeroes(int[][] matrix) {
if(matrix.length==0){
return;
}
int row=matrix.length;
int col=matrix[0].length;
// 标记需要清0的行的数组,需要清0则标记为1,默认是0
int[] rowMark=new int[row];
// 标记需要清0的列的数组,需要清0则标记为1,默认是0
int[] colMark=new int[col];
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if(matrix[i][j]==0){
rowMark[i]=1;
colMark[j]=1;
}
}
}
// 需要清0的行,所有行元素设置为0
for (int i = 0; i <row ; i++) {
if(rowMark[i]==1){
for (int j = 0; j < col; j++) {
matrix[i][j]=0;
}
}
}
// // 需要清0的列,所有列元素设置为0
for (int i = 0; i <col ; i++) {
if(colMark[i]==1){
for (int j = 0; j < row; j++) {
matrix[j][i]=0;
}
}
}
}
4.3 z形打印二位数组
public class Z形打印二位数组{
public static void main(String[] args) {
int[][] arr = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 },
{ 13, 14, 15, 16 } };
print(arr);// 1 2 5 9 6 3 4 7 10 13 14 11 8 12 15 16
}
/**
* Z形打印矩阵
*
* @param arr
*/
static void print(int[][] arr) {
int row = 0, col = 0;
int maxRow = arr.length - 1, maxCol = arr[0].length - 1;
boolean direct = true;// true: 箭头走上坡,false:箭头走下坡
while (row <= maxRow && col <= maxCol) {
if (direct) {// true: 箭头走上坡
System.out.print(arr[row][col] + " ");
if (row > 0 && col == maxCol) {// 竖向箭头向下
direct = !direct;// 非横向箭头改为下坡方向
row++;
continue;
} else if (row == 0 && col < maxCol) {// 横向箭头向右
direct = !direct;// 非横向箭头改为下坡方向
col++;
continue;
} else {// 非横竖向箭头走上坡方向
row--;
col++;
}
} else {// false:箭头走下坡
System.out.print(arr[row][col] + " ");
if (row == maxRow && col < maxCol) {// 横向箭头向右
direct = !direct;// 非横向箭头改为上坡方向
col++;
continue;
} else if (row < maxRow && col == 0) {// 竖向箭头向右
direct = !direct;// 非横向箭头改为上坡方向
row++;
continue;
} else {// 非横竖向箭头走下坡方向
row++;
col--;
}
}
}
}
}
4.4 边界为1的最大子方阵
class 边界为1的最大子方阵{
public int largest1BorderedSquare(int[][] grid) {
int result = 0;// 返回结果
int rows = grid.length;// 总行数
int cols = grid[0].length;// 总列数
int[][] left = new int[rows][cols];
int[][] up = new int[rows][cols];
int[][] right = new int[rows][cols];
int[][] down = new int[rows][cols];
// 下面开始初始化4个数组
// 左上
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (grid[i][j] == 1) {
left[i][j] = j > 0 ? left[i][j - 1] + 1 : 1;
up[i][j] = i > 0 ? up[i - 1][j] + 1 : 1;
}
}
}
// 右下
for (int i = rows - 1; i >= 0; i--) {
for (int j = cols - 1; j >= 0; j--) {
if (grid[i][j] == 1) {
right[i][j] = j < cols - 1 ? right[i][j + 1] + 1 : 1;
down[i][j] = i < rows - 1 ? down[i + 1][j] + 1 : 1;
}
}
}
// 下面计算结果
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
int minOne = Integer.min(right[i][j], down[i][j]);
for (; minOne > 0; minOne--) {
int minTwo = Integer.min(left[i + minOne - 1][j + minOne - 1], up[i + minOne - 1][j + minOne - 1]);
if (minOne <= minTwo) {
result = Integer.max(result, minOne);
break;
}
}
}
}
return result * result;
}
}
4.5 子数组最大累加和
class 子数组最大累加和 {
public int maxSubArray(int[] nums) {
int result = nums[0];
for(int i = 1;i < nums.length;i++){
nums[i] = nums[i] + Integer.max(nums[i - 1],0);
result = Integer.max(result,nums[i]);
}
return result;
}
}
4.6 子矩阵最大累加和
// N^3时间复杂度
private static int maxSum(int[][] matrix) {
int beginRow = 0;// 以它为起始行
final int M = matrix.length;
final int N = matrix[0].length;
int[] sums = new int[N];// 按列求和
int max = 0;// 历史最大的子矩阵和
while (beginRow < M) { // 起始行
for (int i = beginRow; i < M; i++) {// 从起始行到第i行
// 按列累加
for (int j = 0; j < N; j++) {
sums[j] += matrix[i][j];
}
// 累加完成
// 求出sums的最大和子数组O(n)
int t = Case05_MaxSubArray.findByDp(sums);
if (t > max)
max = t;
}
// 另起一行作为起始行.把sums清零
Arrays.fill(sums, 0);// 快速地将sums的每个元素都设定为0
beginRow++;
}
return max;
}