目录
数组的定义与使用
数组的定义
什么是数组
一次定义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))); }