文章目录
前言
- 了解数组的冒泡排序
- 了解数组的二分查找
- 会调用API中操作数组的常用方法,比如:arraycopy, sort,binarySearch,toString方法
一、排序操作
需求:完成对int[] arr = new int[]{2,9,6,7,4,1}数组元素的升序排序操作。
冒泡排序:
对未排序的各元素从头到尾依次比较相邻两个元素的大小关系,如果前一个元素大于后一个元素则交换位置,经过第一轮比较后可以得到最大值,此时最大值就已经在数组的最后一位了,所以,在第二次排序的时候,就可以不用遍历到最后一个元素,第二轮比较后出现第二大值等。
针对int[] arr = new int[]{ 2, 9, 6, 7, 4, 1 }数组元素做排序操作:
该数组有6个元素,只需要5轮比较。
第1轮比较:需要比较5次,比较完出现第一个大值。
第2轮比较:需要比较4次,比较完出现第二大值。
第3轮比较:需要比较3次,比较完出现第三大值。
...
可以看出如有N个元素,则需要N-1轮比较,第M轮需要N-M次比较。
交换数组中两个元素的方法
public class ArrayUtils {
private ArrayUtils() {}
// 通过索引交换数组索引处值
public static void swap(int[] arr, int index1, int index2) {
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
}
排序代码:
public class ArrayUtils {
private ArrayUtils() {}
public static void swap(int[] arr, int index1, int index2) {
int temp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = temp;
}
public static void bubbleSort(int[] arr) {
//第一轮:
for (int i = 1; i <= arr.length-1; i++) {
if (arr[i - 1] > arr[i]) {
swap(arr, i - 1, i);
}
}
//第二轮:
// 此时,最大值已经排在最后,
// 所以再次遍历排序的时候,就不用再遍历到最后一位了
for (int i = 1; i <= arr.length - 2; i++) {
if (arr[i - 1] > arr[i]) {
swap(arr, i - 1, i);
}
}
//第三轮:
for (int i = 1; i <= arr.length - 3; i++) {
if (arr[i - 1] > arr[i]) {
swap(arr, i - 1, i);
}
}
// 第四轮呢?
// 有n个元素排序,就需要进行n-1次循环操作
// 所以我们可以使用双重for循环来进行排序
// 外层for循环控制排序的次数
// 内层for循环进行数组的排序操作
}
}
所以,最后的冒泡排序代码如下:
public static void bubbleSort(int[] arr) {
for (int times = 1; times <= arr.length - 1; times++) {
//times表示第几轮比较,值为:1,2,3,4,5
for (int i = 1; i <= arr.length - times; i++) {
if (arr[i - 1] > arr[i]) {
ArrayUtils.swap(arr, i - 1, i);
}
}
}
}
二、二分查找
猜数字游戏:电脑随机生成一个[ 1 , 100 ]之间的商品价格,等玩家来猜,猜之后,电脑提示出三种结果:你猜的数偏大,偏小和猜中了。
此时为了以最少次数猜中 ,玩家决定
先猜(1+100)/ 2的商50,如果此时电脑提示猜的偏小了,那就能推断出该随机数在[ 51 , 100 ]之间,此时再猜(51+100)/ 2的商75,如果电脑提示猜大了,那么该随机数必在[ 51 , 74 ]之间,那么继续猜(51+74)/2的商,如此每次都可以排除剩下结果一半的可能性,直到猜到为止。
关键字:以最少的次数猜中,在规定的时间(10分钟)猜中最多。
代码如下:
public class ArrayUtils {
private ArrayUtils() {}
// 二分查找法
public static int binarySearch(int[] arr, int key) {
int low = 0;
int high = arr.length - 1;
while (low <= high) {
int mid = (low + high) / 2;
int midVal = arr[mid];
if (midVal < key) {
low = mid + 1;
} else if (midVal > key) {
high = mid - 1;
} else {
return mid;
}
}
// 没有找到
return -1;
}
}
三、Arrays API
Arrays工具类中的方法,一般都是使用static修饰的。
打开JDK帮助文档,搜索Arrays类,进入该类的文档页面,去找toString方法,发现在Arrays类中有多个toString方法,他们之间属于重载关系,分别用于打印不同类型的数组。
如: 查看Arrays类中将int类型数组转换成字符串的toString方法。
如果看方法列表看不懂怎么使用,使用鼠标左键点击该方法名称,进入该方法的详细:
四、Arrays常用方法
4.1、Arrays.toString()
将数组转化为字符串,可以通过此方法,快速查看数组中的元素,如果不用此方法,我们需要查看数组的元素就需要遍历数组通过数组的索引查看元素,这样很麻烦,有了toString方法,我们就可以直接查看数组的元素
int[] a = {1,2,3,4,5};
System.out.println(Arrays.toString(a));
// 输出格式:[1,2,3,4,5]
4.2、Arrays.sort()
给数组进行排序,默认是升序排列,底层采用的就是上面所说的冒泡排序
int[] a = new int[5]{5,4,3,2,1};
Arrays.sort(a); // 1 2 3 4 5
System.out.println(Arrays.toString(a));
// [1,2,3,4,5]
4.3、Arrays.equals()
比较的是两个数组的内容是否相同
int[] a = {1,2,3};
int[] b = {1,2,3};
boolean isSame = Arrays.equals(a,b);
//true
注意:
- a.equals(b),这样的比较,是比较的两个数组地址是否一样
- 除开基本数据类型以外,其余的引用类型的数据我们一般比较的是内容是否相同,而这样我们就需要重写equals方法,当然,一些引用类型的类在底层就已经重写了这个方法,当我们需要自己创建一些类并且需要判断根据这个类创建的对象的内容是否相等的时候我们就需要自己重写equals方法
4.4、Arrays.binarySearch()
在数组中查找元素,该方法底层就是上面所说的二分查找法
如果找到元素,返回值就是该元素在是数组中的索引值
如果没有找到,返回的值是小于0
的
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int index = Arrays.binarySearch(arr, 8);
System.out.println(index);// 7
4.5、Arrays.copyOf()
拷贝数组
Arrays 中提供了数组复制的方法,copyOf(int[] original, int newLength) 复制指定的数组,截取或者用0填充。
System类中提供了数组元素拷贝的方法,并且支持任意类型的数组拷贝,而不仅仅是int类型数组。
// copyOf
// 截取场景
int[] arr = new int[] { 10, 20, 30, 40, 50, 60, 70 };
// int[] newArr = Arrays.copyOf(arr, 3);
// 填充场景
int[] newArr = Arrays.copyOf(arr, 10);
System.out.println(Arrays.toString(newArr));
// System.arraycopy()
int[] arr2 = {1,2,3,4};
int[] newArr2 = new int[10];
System.arraycopy(arr2,0,newArr2,0,arr2.length);
System.out.println(Arrays.toString(newArr2));
常用的也就这些,如需其他方法,可以去API文档中查看