Java数组

1、Java中的数组

数组是相同数据类型的多个数据的容器。
这些元素按线性顺序排列。所谓线性顺序是指除第一个元素外,每一个元素都有唯一的前驱元素;除最后一个元素外,每一个元素都有唯一的后继元素。(“简单理解就是:一个跟一个顺序排列”)。

创建格式(一维数组):

格式 1. 数据类型[] 数组名称 = new 数据类型[数组长度];

格式 2. 数据类型[] 数组名称 = {数组内容 1,数组内容 2,数组内容 3…数组内容 n};

格式 3. 数据类型[] 数组名;

  1. 格式 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,经过纸上推演这才恍然大悟,明白为什么极端情况也能正确运行。