JAVA自学日记2-数组

这篇博客记录了JAVA自学的第二天,主要探讨数组的创建、操作和排序。介绍了如何创建数组,包括一维和二维数组,并通过实践题目讲解了数组的最小值查找、反转和排序。此外,详细阐述了Arrays工具类的使用,如数组复制、排序、查找、填充和转换,以及在二维数组上的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

学的进度很慢,想日报一样把每天新学的东西略作总结,会更有收获,就权当是个记录吧。

day_2 数组

数组的长度是不可变的,一旦分配好空间,是多长,就多长,不能增加也不能减少。

·创建数组的几种方法

以创造一个长度为5的数组为例:

int a[]=new int[5];//创建长度为5的数组,但不指定数组内的元素
int a[]=new int[] {1,2,3,4,5};//创建数组a,a含有五个元素,分别是1,2,3,4,5。
int a[]={1,2,3,4,5};//省略new int[]也是可以的。
int a[]=new int[5] {1,2,3,4,5};//即指定长度又指定内容的方法,但是长度必须和内容相匹配。

实践题目

1.数组最小值

首先创建一个长度是100的数组
然后给数组的每一位赋予随机整数
通过for循环,遍历数组,找出最小的一个值出来

int a[]=new int[100];
        for(int i=0;i<100;i++) {
            a[i]=(int) (Math.random() * 100);//Math.random() :到一个0-1之间的随机浮点数
            System.out.println(a[i]);
        }
        int max=a[0];
        int weishu=0,j=0;
        for (j=0;j<100;j++){
            if (a[j]>max){
                max=a[j];
                weishu=j;
            }
        }
        System.out.println("最大值为数组中的第"+weishu+"位,它的值为:"+max);

或者,也可以用增强型for循环

        int a[] = new int[100];
        for (int i = 0; i < 100; i++) {
            a[i] = (int) (Math.random() * 100);//Math.random() :到一个0-1之间的随机浮点数
            System.out.println(a[i]);
        }
        int max = 0;
        for (int each : a) {
            if (each > max)
                max = each;
        }
        System.out.println("数组中的最大值为:" + max);
2.反转数组

首创建一个长度是10的数组,并填充随机数,对这个数组实现反转效果。这个题理解好了,对之后的反转链表会有帮助。
思路:
对于一个长度为n的数组a[n],下标为0——n-1。数组反转后,其中内容以n/2为界实现镜像翻转,即,a[0]与a[n-1]对换,a[1]与a[n-2]对换……以此类推。

        int a[]=new int[10];
        for(int i=0;i<10;i++) {
            a[i]=(int) (Math.random() * 100);//Math.random() :到一个0-1之间的随机浮点数
            System.out.println(a[i]);
        }//随机生成一个10位数组

        int space=0,j=0;
        for (j=0;j<5;j++){
        /*这里的5是10/2得到。考虑长度为n的数组,当n为奇数时,原数组最中间的数有两位,
        分别是a[int(n/2)]与a[int(n/2)+1],根据代码,j会累加到n/2向下取整,
        直到实现a[int(n/2)]与a[int(n/2)+1]对调;当n为偶数时,中间位只有一位即a[n/2],
        j会累加到a[n/2-1],因为数组反转后a[n/2]仍为居中那位,因而不必反转。
        因此此代码奇数偶数都适用。*/
            space=a[j];
                a[j]=a[10-1-j];//注意长度为n的数组,下标最大值为n-1,我第一次跑的时候忘记在n的基础上-1,然后报错了。
                a[(10-1-j)]=space;
            }
        System.out.println("反转后数组为:");
        for(int i=0;i<10;i++) {
            System.out.println(a[i]);
        }
3.数组的排序

这个也可以说是经典问题了,给出任意长度为n的数组,将其按照数值升序/降序排序。

冒泡排序
我只能想到冒泡法……,以n=10,实现降序排列为例:

        int a[] = new int[10];
        for (int i = 0; i < 10; i++) {
            a[i] = (int) (Math.random() * 100);//Math.random() :到一个0-1之间的随机浮点数
            System.out.println(a[i]);
        }

        int space, j;
        for (int m=9;m>1;m--){//最大值是9是因为下标比长度小一位
            for (j = 0; j < m; j++) {
                if (a[j] < a[j + 1]) {//如果实现升序排列,把<改为>即可
                    space = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = space;
                }
                //紧挨的元素两两比较,最终把最小值放到数组末尾
            }
        }
        System.out.println("排序后数组为:");
        for (int i = 0; i < 9; i++) {
            System.out.println(a[i]);
        }

经过后来的学习,我知道了冒泡法是排序当中优先级很低的方法,它的时间复杂度为O(n2)。关于时间复杂度的计算,可以参考如下视频:link
但是网上看了一下冒泡排序的复杂度计算,很多没有过程,在这里浅析一下冒泡排序的时间复杂度计算:
冒泡排序的意义为:“排除已经通过冒泡实现了顺位的部分,将数组中剩余的部分的相邻的元素两两比较,每次比较中,如果出现逆序情况,则交换这组数据的位置以实现 ‘冒泡’ 。”
假设原数组长度为n,剩下需要比较的数组长度为m,则由于每次需要比较的数组部分的长度在递减,即(m=n;m>1;m–;),所以对于某固定的m,执行【比较】的次数为(m-1)+(m-2)+(m-3)+…+1=m*(m-1)/2。
“每次比较中,如果出现逆序情况,则交换这组数据的位置”。不难看出,在最好的情况下,数组本身就是顺序的,不需要进行元素交换(0次交换),所以执行交换次数为0次;在最坏的情况下每次都要进行交换,执行【交换】的次数为3*(m-1)次(因为交换这个步骤有3行代码)。
综上,在最坏的情况下代码执行的次数为:
在这里插入图片描述
在计算时间复杂度时,只考虑最高阶项,求和符号可以被忽略,加好右侧的项可以忽略;且不考虑系数,m最大等于(n-1),所以带入上式得出,冒泡排序的时间复杂度为O(n2)。

当时还想到另一种排序思路:从原数组中依次取出元素进行排列,每次将新取出的元素按照大小顺序插入已排好的(之前取出的)有序数组中,直到所有元素都被取出。这种方法又称为插入排序法。但是它的时间复杂度仍然是O(n2),因此同样不推荐。

更优的解法
对于排序,推荐的方法有快速排序法、归并排序法和堆排序。它们的时间复杂度都是O(N*logN),其空间复杂度分别是O(logN)、O(N)、O(1)。但值得注意的是,快速排序法是不稳定的,不稳定的意思是指,算法在排序过程中可能会使两个大小相等的元素之间发生交换,如果只是单纯的比较数值大小,确实没什么影响,但是有时候这个数值仅仅是某组数据中提取的一个标签,它们的位置交换会带来不可预测的后果。
目前我的学习只支持我理解这几个算法的原理,自己写出代码还有些困难,我想放在后面学习算法知识的时候再来填坑,这里不再赘述。

·复制数组的方法

System.arraycopy(src, srcPos, dest, destPos, length)

src: 源数组
srcPos: 从源数组复制数据的起始位置
dest: 目标数组
destPos: 复制到目标数组的起始位置
length: 复制的长度

练习:合并数组

将两个长度在5–10之间,且元素均为100内的整随机数的数组进行合并。
由于数组长度是固定不可更改的,因此只能新创建一个数组等于前两者的合并。
用到的方法:用random取随机数;用增强型for循环 for (int each : nums)遍历数组;用 System.arraycopy复制数组。

        //利用Random类生成两个[5,10]之间的随机数n、m作为数组a,b的长度。
        //记得要在最前面调库“import java.util.Random;”
        Random rand = new Random();
        int n=rand.nextInt(5 + 5);
        int m=rand.nextInt(5 + 5);
        int a[] = new int[n];
        int b[] = new int[m];

        //给a,b数组填充0-100的随机数
        for (int i = 0; i < n-1; i++) {
            a[i] = rand.nextInt(100);
        }
        for (int i = 0; i < m-1; i++) {
            b[i] = rand.nextInt(100);
        }

        //用增强型for循环打印a,b数组
        System.out.println("a数组:");
        for (int each : a) {
            System.out.println(each);
        }
        System.out.println("b数组:");
        for (int each : b) {
            System.out.println(each);
        }

        //之后再生成一个新数组,长度为a,b数组长度的和
        int c[] = new int[m+n];
        //利用System.arraycopy复制数组
        System.arraycopy(a,0,c,0,n);
        System.arraycopy(b,0,c,n,m);
        System.out.println("c数组:");
        for (int each : c) {
            System.out.println(each);
        }

·二维数组

二维数组,又被称为数组的数组,即该数组中的每个元素也是数组。创建二维数组的方法:

int[][] a = new int[内含数组的个数][每个数组的长度];

在实际应用中,可以只指定内含数组的个数而把长度空着,因为这些内含数组不一定都是等长的,如果在上式中一旦指定长度,表示所有元素的长度都一样。
需要注意的是,如果要访问某内含数组的元素,必须先规定该元素所在内含数组的长度。

练习:二维数组中的最大值

对于一个10x10的二维数组,其中数值为0-100的随机数,找出二维数组中的最大值。

        Random rand = new Random();
        int a[][]=new int[5][5];
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
            int num=a[i][j] = rand.nextInt(100);
            System.out.print(num+" ");//每行代表一个一维数组,子数组中的元素以空格分开
            }
            System.out.println("");//每个内含一维数组打印完毕后提行
        }
        int max=0;
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                if (a[i][j]>max)
                        max=a[i][j];
            }
        }
        System.out.println("数组a中最大值为"+max);

当然,打印二维数组也可以用嵌套增强型for循环:

for (int row[] : a) {//遍历二维数组a中的每一行row[]
            for (int each : row) {
                System.out.print(each + "\t");
            }
            System.out.println();
        }

·数组工具Arrays(需要import java.util.Arrays;)

1.复制

生成一个新数组,该数组为已有数组a中,从第b个元素开始起到第c个元素为止但不包括第c个元素的复制,

Arrays.copyOfRange(a,b,c)
2. 排序

对a数组按照升序排序:

Arrays.sort(a);
3.查找某元素位置

查找a数组中特定原数值的位置,将返回该元素的下标值。

Arrays.binarySearch(a, 元素值);

当该元素值不唯一时,返回值也不唯一确定。

4.填充数组

将数组中填满某相同的元素a。

Arrays.fill(a, 要填充的值);
5. 转化字符串

将数组a转换成字符串,通常用在打印时。注意这个方法不适用二维数组,二维数组可以先强制for循环再转化字符串打印。

Arrays.toString(a);
6.判断两数组是否相同

判断a,b数组是否相同并返回一个布尔值,ture表示相同,false表示不同。

Arrays.equals(a, b);
练习:用Arrys方法对一随机5*8的二维数组排序

参考解答:

        //生成一5*8的二维数组,其元素为100内的随机整数
        Random rand = new Random();
        int a[][]=new int[5][8];
        for (int i=0;i<5;i++){
            for (int j=0;j<8;j++){
                a[i][j] = rand.nextInt(100);
            }
        }
        //打印数组a
        System.out.println("数组a为");
        for (int[] row:a){
            System.out.println(Arrays.toString(row));
        }
        //对二维数组展开为一维数组
        int b[]=new int[40];
        int destpos=0;
        for (int[] row:a){
            System.arraycopy(row,0,b,destpos,row.length);
            destpos=destpos+row.length;
        }
        System.out.println(Arrays.toString(b));

        //对一维数组进行排序,查看排序结果
        Arrays.sort(b);
        System.out.println(Arrays.toString(b));
        int srcpos=0;

        //把排序后的一维数组b的元素重新赋到二维数组a中。
        //第一次写的时候用了下面这种方法,虽然后来反应过来,强制for循环只能读取数值,不能改写!但是这里运行的结果却又是对的,感到有些疑惑。
       /*
        for (int[] row:a){
            System.arraycopy(b,srcpos,row,0,8);
            srcpos=srcpos+8;
        }*/

        //用一般for循环实现:
        int row_num;
        for (row_num=0;row_num<5;row_num++){
            a[row_num]=Arrays.copyOfRange(b,srcpos,srcpos+a[row_num].length);
            srcpos=srcpos+a[row_num].length;
        }

        System.out.println("排序后的a数组为:");
        for (int[] row:a) {
            System.out.println(Arrays.toString(row));
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值