java-day14
目录
早上
第一节课
工具类
1、类中很多static方法,使用类名可以很方便的直接调用
2、这些方法可以解决我们在开发遇到的常见问题
对于逻辑问题的解决
1.理解问题,搞清楚自己需要完成一件什么样的事情/功能
2.分析问题,搞清楚这个事情/功能在实现的使用会有什么特点、规律
3.代码实现,把之前分析得到的特点、规律转换java语言来表示出来
4.测试代码,运行代码看是否能够成功,在一些特殊的情况下是否会有bug出现。
5.重构代码,考虑代码结构是否可以调整,使代码变得简洁明了
6.封装代码,考虑代码是否可以进行封装,以便可以使用传参的方式进行调用,这样代码可以变得更加灵活多变。同时对该封装好的代码进行重复调用,以便重复利用。
回顾几个排序
冒泡排序
规则:在一组数据中,从左到右,俩俩比较,然后把较大的数据往前推,一轮下来之后,最大的一个数据就被推到了最右边。
例如: 2 1 4 9 8 5 3 第一轮第1次比较后 1 2 4 9 8 5 3 第一轮第2次比较后 1 2 4 9 8 5 3 第一轮第3次比较后 1 2 4 9 8 5 3 第一轮第4次比较后 1 2 4 8 9 5 3 第一轮第5次比较后 1 2 4 8 5 9 3 第一轮第6次比较后 1 2 4 8 5 3 9
//冒泡排序
public void test10(int[] arr){
//获取到数组的长度
int len = arr.length;
//外层循环控制一共比较几轮
for(int i=0;i<len-1;i++){
//内层循环控制每轮比较多少次数,每轮比较的次数是有变化的
for(int j=0;j<(len-i-1);j++){
//如果前一个数据比后一个数据大
if(arr[j]>arr[j+1]){
//交互这个俩个数据的位置
arr[j] = arr[j] ^ arr[j+1];
arr[j+1] = arr[j] ^ arr[j+1];
arr[j] = arr[j] ^ arr[j+1];
}
}
//这个输出,可以看到每一轮比较结束后的结果是怎样的
System.out.println("\t"+Arrays.toString(arr));
}
}
选择排序
2 1 4 9 8 5 3
规则:每一轮在待排序的区域中比较找到一个最小值后,把这个最小值放到已经排好顺序的区域的末尾,剩下的部分成一个新的待排序部分,重复上面的步骤直到排序结束。
2 1 4 9 8 5 3
第一轮从待排序区中找到一个最小值,然后和第一个位置的数字交互位置
第二轮从新的待排序区中找到一个最小值,然后和第二个位置的数字交互位置
第三轮从新的待排序区中找到一个最小值,然后和第三个位置的数字交互位置
第四轮从新的待排序区中找到一个最小值,然后和第四个位置的数字交互位置
第五轮从新的待排序区中找到一个最小值,然后和第五个位置的数字交互位置
第六轮从新的待排序区中找到一个最小值,然后和第六个位置的数字交互位置
注意,操作的核心目标: 1.每轮找到的最小值应该存放的下标位置是什么 2.每轮找到的最小值现在的下标位置是什么 3.找到之后,让这俩个位置的值进行交互就可以了
//选择排序
public void test11(int[] arr){
//数组的长度
int len = arr.length;
//min_now_index表示最小值【当前】在什么位置
int min_now_index;
//min_should_index表示最小值【应用】在什么位置
int min_should_index;
//外层循环,可以一共要比较多少轮,同时这个变量i刚好是每轮我们需要指定的最小值应该存放位置。
for(int i=0;i<len-1;i++){
//每一轮i的值,刚好就是本轮最小值应该存放的位置。
min_should_index = i;
//假设当前i的位置就是本轮最小值的实际位置
min_now_index = i;
//内层循环,负责每轮找出当前未排序区中的一个最小值的实际位置的下标
for(int j=i+1;j<len;j++){
//哪个数据小,就把这个数据下标赋值给min_now_index
//目的是让了min_now_index变量中始终保持当前未排序区中的最小值的位置
if(arr[j]<arr[min_now_index]){
min_now_index = j;
}
}
//内层循环结束后,就明确了当前未排序区中的最新值的下标,以及这个最小值应该存放在什么位置
//接下来可以进行交互位置
if(min_now_index != min_should_index){
int temp = arr[min_now_index];
arr[min_now_index] = arr[min_should_index];
arr[min_should_index] = temp;
}
}
}
第二/三节课
插入排序
规则:把数组分成俩部分,将后面部分的数据一个一个的和前面部分数据的元素进行比较,如果我们指定的元素比前面部分的元素小,那么就将前面的元素往前移动一步,直到没有比我们这个指定元素还小元素了,那么这个位置就是需要插入的地方。
2 1 4 9 8 5 3
例如,我们可以把这个数组,从2的位置进行分开,分成俩组,左边一组是2,右边一组是 1 4 9 8 5 3 ,左边一组是已经排好顺序的序列,右边一组是没有排好顺序的序列。 我们需要从右边的待排序序列中,依次拿出每一个值,和左边已经排好顺序的数字进行比较,比较的目的是为了给我们当前操作的右边数字找一个合适的位置进行插入,注意这个操作元素的位置有可能是不需要移动的,因为刚才不移动就保持了正常顺序。
//插入排序
public void test1(){
int[] arr={2,1,4,9,8,5,3};
System.out.println(Arrays.toString(arr));
//排序操作
/**
每轮完核心目标
1、拿到右边要操作的数据
2、找出左边的核心位置
3、最后把右边当前操作的数据插入到左边合适的位置
*/
int len = arr.length;
int currentValue=0;//当前要操作的数据
int insertPosition=0;//当前合适的插入位置
/**
外层循环控制比较的轮数
同时变量i的值还是每一轮我们要操作的右边第一个数字的下标
*/
for(int i = 1;i<len;i++){
//提前保存要操作的值
currentValue = arr[i];
//假设变量就是我们要插入的位置
insertPosition = i;
//每次比较如果发现arr[j]比当前要操作的数字大
/**
内层循环控制每轮比较的次数,以及比较的顺序
同时变量j的值还是左边第一个数据的下标
例如: 1 2 4 8 9 | 5 3
我们拿着5要依次和这边的9 8 4 2 1比较
下标顺序:4 3 2 1 0
(j的下标变化规律)
*/
for(int j=i-1;j>=0;j--){
if(arr[j]>currentValue){
//就把这个大的数字往后移动一个位置
arr[j+1] = arr[j];
//然后记录一下这个位置(很可能是要插入的位置)
insertPosition = j;
}else{
//发现比currentValue小的值,
//上一个值的位置就是要插入的位置
break;
}
}
/**
内层循环结束后,我们要把当前操作的值currentValue插入到
指定位置insertPosition定位置insertPosition,如果insert
Position和当前i值相等,说明当前操作的这个值currentValue
是不需要移动的。
*/
if(insertPosition != i){
arr[insertPosition] = currentValue;
}
System.out.println("\t"+Arrays.toString(arr));
}
System.out.println(Arrays.toString(arr));
}
案例:返回随机中奖号码
public String test2(String [] tels){
int random = (int)(Math.random()*tels.length);
return tels[random];
}
下午
案例:返回一个四个字符长度的验证码,验证码包括字母和数字
其中字母(a-z,A-Z),数字(0-9)
应用:toCharArray():将String转为数组、字符串拼接、random
二维数组
实例:
假定有一个旅馆,共三层楼,每层楼中有不同的房间数量 第一层楼有4间房 第二层楼有3间房 第三层楼有5间房 某一天客户入住的情况如下:
这样就使用了一个二维数组对象room,来表示出当前旅馆中三层楼中的入住情况。
二维数组的声明和创建
在堆区内存中创建有一块连续的内存开年,有一块连续的内存空间,共有四个元素位置,每一个元素位置中已经放置好数据。这个数据是一位数组对象,同时这里存放的每一个以为数组对象中,都有三个元素位置
int[][] a = new int [4][3];
//等价于
int[][] a = new int[3];
a[0] = new int[3];
a[1] = new int[3];
a[2] = new int[3];
a[3] = new int[3];
//还等价于
int[][] a = {
{0,0,0},
{0,0,0},
{0,0,0},
{0,0,0},
};
错误的情况
int [][] a = new int [][];//error
二维数组的赋值
普通赋值
int [][] a = new int[4][3];
int[] b1 = a[0];
b1[0] = 10;
b1[1] = 10;
b1[2] = 10;
//等价于
a[0][0]=10;
a[0][1]=10;
a[0][2]=10;
a[1][0]=10;
a[1][1]=10;
a[1][2]=10;
a[2][0]=10;
a[2][1]=10;
a[2][2]=10;
a[3][0]=10;
a[3][1]=10;
a[3][2]=10;
int [][] a = new int[4][];
a[0][0] = 10;
a[1][0] = 20;
a[1][1] = 20;
a[2][0] = 30;
a[2][1] = 30;
a[2][2] = 30;
a[3][0] = 40;
a[3][1] = 40;
a[3][2] = 48;
a[3][3] = 40;
特殊的赋值方式
int[][] a = {
{1,2,3},
{4,5,6},
{7,8,9},
};
int[][] a = new int[][]{
{1,2,3},
{4,6},
{7,8,9},
};
错误的赋值情况
//数组元素已经写出来了,可以明确表示粗长度为3
//没必要中括号再写个3.反而会报错
int[][] a = new int[3][]{
{1,2,3},
{4,6},
{7,8,9},
};
使用循环给二维数组赋值
int[][] arr = new int[3][4];
for(int i=0;i<arr.length;i++){
//拿到一维数组中存放的房间数
for(int j=0;j<arr[i].length;j+;j++){
arr[i][j]=(int)(Math.random()*100);
}
}
for(int i=0;i<arr.length;i++){
int[] t = arr[i];
//直接把一维数组输出
System.out.println(Arrays.toString(t));
}
随机二维数组
//随机二维数组
public void test5(){
int [][] arr;
arr = new int[(int)(Math.random()*10)][];
for(int i=0;i<arr.length;i++){
arr[i] = new int[(int)(Math.random()*10)];
for(int j=0;j<arr[i].length;j++){
arr[i][j]=(int)(Math.random()*10);
}
}
for(int k=0;k<arr.length;k++){
System.out.println(Arrays.toString(arr[k]));
}
}
杨辉三角
/*
杨辉三角 数字 空格 数组下标
1 1 4 0 1
1 1 2 3 1 11
1 2 1 3 2 2 121
1 3 3 1 4 1 3 1331
1 4 6 4 1 5 0 4 14641
*/
public void test6(int line){
int[][] arr = new int[line][];
//根据规律构建出二维数组并且赋值
for(int i=0;i<arr.length;i++){
arr[i] = new int[i+1];
//循环给二维数组中的每个位置赋值
for(int j=0;j<arr[i].length;j++){
if(j==0 || j==arr[i].length-1){
arr[i][j]=1;//特殊情况
}else{
//规律
arr[i][j] = arr[i-1][j]+arr[i-1][j-1];
}
}
}
//打印杨辉三角
for(int i=0;i<arr.length;i++){
//空格
for(int j=(arr.length-i-1);j>=0;j--){
System.out.print(" ");
}
//数字
for(int k=0;k<arr[i].length;k++){
System.out.print(arr[i][k]+" ");
}
System.out.println();
}
}