算法学习之数组

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():拷贝数组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值