1、顺时针打印二维数组
1、问题
2、代码
package com.lanqiao.vidio;
public class PrintCol {
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);
}
public static void print(int[][] arr)
{
int leftUpRow = 0,leftUpCol = 0;
int rightDownRow = arr.length;
int rightDownCol = arr[0].length;
while(leftUpRow<=rightDownRow&&leftUpCol<=rightDownCol) {
int c = leftUpRow;
int r = leftUpCol;
while(r<rightDownCol)
{
System.out.print(arr[0][r]+" ");
r++;
}
r--;
c++;
while(c<rightDownRow)
{
System.out.print(arr[c][r]+" ");
c++;
}
c--;
r--;
while(r>=leftUpCol)
{
System.out.print(arr[c][r]+" ");
r--;
}
c--;
r++;
while(c>leftUpRow)
{
System.out.print(arr[c][r]+" ");
c--;
}
leftUpRow++;leftUpCol++;rightDownRow--;rightDownCol--;
}
}
}
2、Z形打印
1、问题
2、代码
package com.lanqiao.vidio;
public class Zprint {
public static void main(String[] args) {
int[][] arr = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
print(arr);
}
public static void print(int[][] arr)
{
int r = 0,c = 0;
int rNum = arr.length-1;
int cNum = arr[0].length-1;
boolean dic = true;//标记走向的bool变量,true:右上走,反之左下走
while(c<=cNum&&r<=rNum)
{
System.out.print(arr[r][c]+" ");
if(dic)//只考虑右上走的情况
{
//当前在第一行,列未到边界,只能向右走
if(r==0&&c<cNum)
{
dic=!dic;//方向切换
c++;//向右走
continue;
}else if(r>0&&c==cNum)//走到最后一列,只能向下走
{
dic=!dic;
r++;
continue;
}else {//其他情况,右上走
r--;
c++;
}
}else {
if(c==0&&r<rNum)
{
dic=!dic;
r++;
continue;
}
else if(r==rNum&&c<cNum)
{
dic=!dic;
c++;
continue;
}
else
{
r++;
c--;
}
}
}
}
}
3、思想
(1)考虑的时候先考虑起点和终点,方向问题
(2)结束的时候是col&&row??
(3)在向右下走的时候只考虑这种情况的边界,反之只考虑另一种情况
(4)注意continue
(5)注意右上走是r–,c++,不是两个都+
3、边界为1的最大子方阵
1、问题
2、代码
package com.lanqiao.vidio;
public class BoundK {
public static void main(String[] args) {
int[][] arr = {
{1,1,1,1,1},
{1,0,0,0,1},
{1,0,0,0,1},
{1,0,0,0,1},
{1,1,1,1,1}
};
System.out.println(bound(arr));
}
public static int bound(int[][] arr)
{
int N = arr.length;
int n = N;
int r = 0,c=0;
while(n>0)//表示框的大小(边长)
{
for(int i=0;i<N;i++)//开始的行
{
if(i+n>N) break;
l3:
for(int j=0;j<N;j++)//开始的列
{
if(j+n>N) break;
r=i;
c=j;
//上方
while(c<j+n)
{
if(arr[r][c]==0) continue l3;
c++;
}
c--;
//右
while(r<i+n)
{
if(arr[r][c]==0) continue l3;
r++;
}
r--;//恢复r
//下
while(c>=j)
{
if(arr[r][c]==0) continue l3;
c--;
}
c++;
//左
while(r>=i)
{
if(arr[r][c]==0) continue l3;
r--;
}
return n;
}
}
n--;
}
return 0;
}
}
3、思想
(1)和上一题差不多,都是从起点开始定探测位置
(2)外层while循环定正方形大小
(3)内层两个循环定起点
(4)分别探测上下左右边是否都正常
4、注意点
(1)注意i和j的范围,如果i加上边长都越界了直接返回
4、子数组最大累加和
1、问题
2、代码
package com.lanqiao.vidio;
public class ArrayBig {
public static void main(String[] args) {
int[] arr = {-1,2,2};
System.out.println(find(arr));
}
public static int find(int[] arr)
{
int ans = arr[0];
int sum = ans;
int left = 0,right=0;//记录最大数组的左右下标
for(int i = 1;i<arr.length;i++)
{
if(sum>=0)
{
sum+=arr[i];
// System.out.println(sum);
}else {
sum=arr[i];
left=i;
}
if(ans<sum)
{
ans=sum;
right=i;
}
}
return ans;
}
}
5、子矩阵的最大累加和
1、问题
2、代码
package com.lanqiao.vidio;
import java.util.Arrays;
public class ArrayMax {
public static void main(String[] args) {
int[][] arr = {
{-1,-1,-1},
{-1,2,2},
{-1,-1,-1}
};
System.out.println(max(arr));
}
public static int max(int[][] arr)
{
int beginRow = 0;//起始行
int M = arr.length;//行数
int N = arr[0].length;//列数
int[] sum = new int[N];//按列求和
int max = 0;//历史最大的子矩阵和
while(beginRow<M)//起始行
{
for(int i=beginRow;i<M;i++)//从起始行开始到第i行
{
for(int j=0;j<N;j++)//按列累加
{
sum[j]+=arr[i][j];
}
//累加完成
//求出sum的最大子数组和
int t = ArrayBig.find(sum);
if(t>max)
max = t;
}
//起始行换行
Arrays.fill(sum, 0);//初始化数组
//另起一行作为起始行
beginRow++;
}
return max;
}
}
3、思想
(1)利用前面单行数组排序的算法数组
(2)从某一行开始,一行计算最大,两行计算最大(同一列相加合并为一行,for循环),三行合并计算最大,然后逐渐行数增加(外层while循环)
4、注意点
(1)每次开始行循环往,数组情况:Arrays.fill(填充数组)
(2)用一个sum数组代表各列情况
6、Arrays常用方法
sort():数组排序
binarySearch():二分查找,找到数组中某个元素
equals():比较两个数组元素是否相同
fill():填充数组,用于初始化数组
copyOf():拷贝数组