JavaSE_03_数组

数组的定义与使用
数组的定义
什么是数组

一次定义N个相同数据类型的变量,我们把这种结构称之为数组。

数组的创建与初始化
数组动态初始化

第一种

数据类型[] 数组名称 = new 数据类型[] {初始化数据} (初始化数据是可选的部分)

第二种

数据类型[] 数组名称 = new 数据类型[num] (num为当前数组的最大元素个数)

在创建数组时若没有使用{}来初始化每个元素值,则每个元素值都是该数据类型的默认值

数组静态初始化

数据类型[] 数组名称 = {初始化数据}

静态初始化,经过javac编译后,就是动态初始化,就是个语法糖

语法糖:只存在编译期之前的语法,编译器为了方便程序员的使用简化的写法

数组的使用
获取数组长度
int[] arr = new int[7];
int len = arr.length;    //arr.length 获取arr数组最大能存储的元素个数
访问数组元素

数组名称[要访问的元素相较于第一个元素的偏移量] (也就是数组名[元素索引])

如果索引越界,那么会引发ArrayIndexOutOfBoundsException

为什么索引要从0开始?

索引其实就是”偏移量“,相较于数组的第一个元素的单位长度。数组的元素是顺序存储的,数组保存的是首元素的地址,要找到别的元素,需要给首元素的地址加一个偏移量

遍历数组
for(int i = 0; i < arr.length; ++i){}
for(int i : arr){}    //i为数组的每个元素

第二种遍历方式只能读取数组的元素值,无法修改,因为每次循环中的i变量是数组每个元素的值拷贝。

关于引用数据类型的理解

JVM把内存划分为6个区域,以下先谈谈“堆区”和“栈区”

方法的调用就是在栈区进行的,每个方法的调用过程,就是一个栈帧的入栈和出栈过程。方法中的局部变量和形参都存储在栈中,当方法调用结束,函数栈帧出栈,方法中的临时变量都会被销毁。

所有对象(比如:数组对象、类的实例化对象、接口的对象)都在堆区存储,只要出现new,后面的对象都开辟到堆区

引用

引用就是起别名,保存的数值是该对象的地址。对于数组对象来说,数组引用实际上就是保存了数组的首元素地址。通过使用该对象的引用,操纵该对象。

int[] arr = new int[]{1,2,3,4,5}    //new后面的部分就是数组对象(在堆上存储),=左边arr的 就是对右边数组对象的引用

所有对象的内存释放,由JVM来进行,啥时候会释放?当一个对象没有任何强引用指向且当前JVM内存不够用时,才会释放这个对象的内存。

public static void func(int[] arr){
    arr = new int[]{1,3,5,7,9};
}
//func()方法调用结束后,形参arr被释放(arr开辟在栈上),new出来的数组对象还存在(该对象开辟在堆区)
数组练习
数组对象转为字符串对象

在JDK中看到某些类后面加s,这种类都是工具类,比如Arrays(数组的工具类),包含数组转字符串方法、数组排序方法等等。比如Collections(集合的工具类)

int[] arr = new int[]{1,3,5,7,9};
String str = Arrays.toString(arr);

System.out.println(arr2Str(arr));
System.out.println(str);
数组拷贝
int len = 某个整数值;
int[] newArr = Arrays.copyOf(arr,len);    //从arr[0],拷贝len长度,若len超出arr.length,以该类型数组元素默认值为超出部分的值

int from=1, to=3;
int[] newArr2 = Arrays.copyOfRange(arr,from,to);    //把[arr[1],arr[3])范围内的值拷贝到新数组

java中的区间都是左闭右开的 [,)

求数组最值

寻找一个数组最值的时候,一开始默认的最值设置为数组内部的元素,不能引入外部变量,一般取首元素为一开始的最值。

二分查找
//给定一个有序整型数组, 实现二分查找
public static boolean binaryFind(int[] arr, int tgt){
    int l = 0, r = arr.length-1;
    while(l <= r){
        int mid = l + ((r - l) >> 1);
        if(tgt < arr[mid]){
            r = mid - 1;
        }else if(tgt > arr[mid]){
            l = mid + 1;
        }else{
            return true;
        }
    }
    return false;
}

public static void main(String[] args) {
    int[] sortedArr = new int[500];
    //构造数组[1,2,3,4,……,500]
    for (int i = 0; i < sortedArr.length; i++) {
        sortedArr[i] = i + 1;
    }
    int num = 399;
    if(binaryFind(sortedArr,num)){
        System.out.println("找到了!");
    }else{
        System.out.println("没找到!");
    }
}
冒泡排序的优化

当待排序的数组形如{1,2,3,4,5,6},则可以:

//给定一个整型数组, 实现冒泡排序(升序排序)
public static void bubbleSort(int[] arr){
    for(int i = arr.length -1; i > 1; --i){
        boolean flag = false;    //状态变量,表示arr[j]有没有和arr[j+1]作交换
        for (int j = 0; j < i; j++) {
            if(arr[j] > arr[j+1]){
                flag = true;
                int tmp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = tmp;
            }
        }
        if(!(flag)){    //在arr[i]之前的元素都有序了,跳出外层循环,排序结束。这样处理可以节约内层循环比较的次数
            break;
        }
    }
}//end of bubbleSort

public static void main(String[] args) {
    int[] arr = new int[]{2,5,8,34,68,9,32,45,78};
    bubbleSort(arr);
    System.out.println(Arrays.toString(arr));
}

//输出
[2, 5, 8, 9, 32, 34, 45, 68, 78]

while循环更多用在只知道循环的终止条件,不关注循环到底走多少次;

for循环明确知道当前循环的次数

找多数元素

给定n个元素组成的整型数组,找出现次数大于n/2的那个数(假定输入数组总存在多数元素)

  • 双指针+计数器

    int major = -1;
    for(int i = 0; i < arr.length; ++i){
        int cnt = 0;
    	for(int j = 0; j < arr.length; ++j){
            if(arr[i] == arr[j]){
                cnt ++;
            }
        }
        if(cnt > arr.length/2){
    		major = arr[i];
            break;
        }
    }
    return major;
    
  • 排序返回中间值

    Arrays.sort(arr);
    return arr[(arr.length - 1) / 2];    //排完序以后数组中间值必为多数元素
    
  • 摩尔投票法

    求解众数问题:

    在一堆元素中,如果选择出m个出现最多的元素,则它们的票数都大于n/(m+1)

    若m==2,则

    public static int[] findTwoMajority(int[] arr){
        int cnt1 = 1, cnt2 = 0;
        int major1 = arr[0], major2 = arr[0];
        int i;
        //找出第一个值不为major1的元素,将其赋值为major2
        for (i = 1; i < arr.length; i++) {
            if(arr[i] != major1){
                major2 = arr[i++];    //把当前值赋给major2后,i自增指向下一位
                cnt2 ++;
                break;
            }
        }
        while(i < arr.length){
            if(arr[i] == major1){
                cnt1 ++;
                i ++;
                continue;
            }else if(arr[i] == major2){
                cnt2 ++;
                i ++;
                continue;
            }else{    //arr[i]找当前票数少的候选人投反对票
                if(cnt1 > cnt2){
                    cnt2 --;
                    if(cnt2 == 0){
                        major2 = arr[i];
                        cnt2 = 1;
                    }
                }else{
                    cnt1 --;
                    if(cnt1 == 0){
                        major1 = arr[i];
                        cnt1 = 1;
                    }
                }
                i ++;
            }
        }//end of while,找到出现最多的两个元素
        int[] ret = new int[2];
        ret[0] = major1;
        ret[1] = major2;
        return ret;
    }
    
    public static void main(String[] args) {
        int[] testArr2 = new int[]{2,7,3,2,3,7,45,7,34,2,78,2,7,2,7,2,7,2,7,2,7};
        System.out.println(Arrays.toString(findTwoMajority(testArr2)));
    }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AbyssPraise

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值