Java数组
1、Java中的数组
数组是相同数据类型的多个数据的容器。
这些元素按线性顺序排列。所谓线性顺序是指除第一个元素外,每一个元素都有唯一的前驱元素;除最后一个元素外,每一个元素都有唯一的后继元素。(“简单理解就是:一个跟一个顺序排列”)。
创建格式(一维数组):
格式 1. 数据类型[] 数组名称 = new 数据类型[数组长度];
格式 2. 数据类型[] 数组名称 = {数组内容 1,数组内容 2,数组内容 3…数组内容 n};
格式 3. 数据类型[] 数组名;
格式 3 属于只创建了数组引用名, 并未在内存创建数组空间。
格式 4. 数据类型[] 数组名称 = new 数据类型[]{内容 1,内容 2,内容 3…内容 n};
一般我们常用的是格式1和格式2。
下标(索引):
可以理解为数组中内容的数字序号,从 0 开始 ,对于长度为 n 的数组,下标的范围是 0~n-1(尤其注意,往往会出现下标越界,不要记错范围)。
可以通过下标的方式访问数组中的每一个元素。
例如: 创建 int 类型数组 nums , 给数组 nums 的 5 下标赋值数据 , 然后打印
int[] nums = new int[10];
nums[1] = 88;
System.out.println(nums[1]);
数组长度获取:
数组名称.length
使用数组不当, 会出现如下问题:
- 数组未赋值: 空指针异常
- 超出长度的下标操作: 数组越界异常
- 注意:数组的长度在创建时就固定了。
最后说一下二维数组的创建,与一维数组类似:
// 数据类型[][] 数组名称 = new 数据类型[数组长度(必填)][选填];
// 注意的是必填的是必须填写的,后边的选填,如果填写了,那么每一个外层数组里面都是一样的数据量,然后可以通过下标进行赋值。如果不填,则需要动态申请nums[0] = new int[]{1,2,3};
int[][] nums = new int[5][];
nums[0] = new int[]{1,2,3};
nums[1] = new int[]{1,2,3,4,5};
System.out.println(nums[0][2]);
System.out.println(nums[1][3]);
/*
int[][] nums = new int[5][3];
nums[0][2] = 1;
// 下面这一句会报错,因为初始化的时候,限定了长度为3
nums[1][4]= 2;
System.out.println(nums[0][2]);
System.out.println(nums[1][4]);
*/
2、案例过程学习记录
1、选队长游戏
学到了使用计数器来模拟报数,并且在为3之后,就归1。第二个是,学到了用一个boolean数组来标记每个人的状态,这样在遍历数组的时候,直接查看这个人状态就知道是否要跳过。
import java.util.Scanner;
public class ChooseCaptain {
public static void main(String[] args) {
/*
选队长游戏规则:
所有人围成一圈,顺序排号。从第一个人开始报数(从 1 到 3 报数),
凡报到 3 的人退出圈子,剩下的人继续报数,最后留下的当选为队长。
求出一组人中的队长是原来第几位同学。
*/
Scanner input = new Scanner(System.in);
System.out.println("请输入共有多少位同学:");
int nums = input.nextInt();
// 初始化一个长度为nums的boolean数组,初始值,默认为false 表示没出局
boolean[] classmates = new boolean[nums];
// 定义计数器count记录1,2,3状态,初始为1
int count = 1;
// 定义一个out数组,记录每次出局的人
int[] out = new int[nums - 1];
// 定义一个k=0,用来标记第几轮淘汰的是哪一位同学,
int k = 0;
// 一定要淘汰 nums-1个人,所以 k < nums -1 ,不够,就继续报数,直到只剩一个人
while(k < nums - 1){
// 每一次遍历数组classmates,模拟报数
for (int i = 0; i < nums; i++) {
// 每一次,只有没有被淘汰的人才能报数,也就是他在classmates中状态是false
if (!classmates[i]) {
// 如果报数为3 ,则淘汰,即把状态改为true,同时在out数组记录
if (count == 3) {
classmates[i] = true;
out[k] = i + 1;
k++;
// 输到3之后,该从1继续
count = 1;
// 如果状态为true,说明淘汰了,那么对count + 1,这是下一个人的报数
} else {
count++;
}
}
}
}
// 遍历输出每一轮淘汰的同学
for (int i = 0; i < nums - 1; i++) {
System.out.println("第" + (i + 1) + "轮出局的是第" + out[i] + "位同学");
}
// 最后classmates中,状态为false的同学为队长
for (int i = 0; i < nums; i++) {
if (!classmates[i]) {
System.out.println("队长是原来的" + (i + 1) + "号同学!恭喜这个b");
break;
}
}
}
}
2、移动零
这个我最开始想到使用双指针,但是想的是从左右各一个,一个从右走,一个从左走,然后仔细想了想发现这样会改变顺序,然后用了额外数组来做,做完想到了快慢指针,然后尝试了一下,真的写出来了,很高兴。因为这个我之前只是见过一次,从来没有自己写出来过,这次居然能实操成功!
3、二分查找
这个真的是大名鼎鼎的算法,刚好前些天,我自己纸上推过,然后写出来过,所以印象深刻,现在也是很清晰的指导它的步骤。因为学习数值分析的时候,知道这个概念和算法思路,可以用来求解方程,但是对于程序上的应用确实会卡住,当我看代码的时候,发现,每次都会让mid+1,或者mid-1,经过纸上推演这才恍然大悟,明白为什么极端情况也能正确运行。