数组
1.数组的定义
数组, 是一个数据容器。 可以存储若干个相兼容的数据类型的数据
1.数组中可以存储基本数据类型的数据, 也可以存储引用数据类型的数据。
2.数组的长度是不可变的,数组的内存空间是连续的。 一个数组一旦实例化完成, 长度不能 改变。
int/double/String[] array = new int/double/String[5];//数组的申明
int/double/String[] array = new int/double/String[]{.....};//赋值
[]
1.int[]表示类型
2.int[5]表示存放的数据个数
3.array[5]表示下标对应的值
2.数组的下标
①下标, 就是数组中的元素在数组中存储的位置索引。
②注意: 数组的下标是从0开始的, 即数组中的元素下标范围是 [0, 数组.length - 1]
③在访问数组中的元素的时候, 注意下标的问题!
如果使用错误的下标访问数组中的元素, 将会出现ArrayIndexOutOfBoundsException
异常!
public class Demo2 {
public static void main(String[] args) {
//数组遍历
int[] arr={1,3,8,54,5,7};
//第一种遍历-通过下标
//数组的长度:arr.length
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("**********");
//第二种--增强for循环
// 依次使用数组中的每一个元素, 给迭代变量进行赋值。
// 此时, 数组中的每一个元素依次给 element 进行赋值。
for (int element : arr) {
System.out.println(element);
}
}
//如果需要在遍历的同时, 获取到数组中的元素下标, 需要使用下标遍历法。
//如果需要在遍历的同时, 修改数组中的元素, 需要使用下标遍历法。
//如果仅仅是想要获取数组中的每一个元素, 不需要下标, 也不需要修改数组中的元素,
//使用增强for循环。 因为这种方式, 遍历的效率比下标遍历法高。
3.函数和数组的联合应用
1.值传递:将保存简单数据的变量作为参数传递
2.址传递:将保存地址的变量作为参数传递
3.址传递优点:让我们可以实现使用一个变量一次传递多个值
public class Demo3 {
public static void main(String[] args) {
//求三个数的和 //直接用数值作为参数传递-值传递
int tmp1 = getMax(3, 4, 6);
System.out.println(tmp1);
//用数组实现求三个数的和-址传递
int[] arr1 = new int[] {3,5,8};
int tmp2 = getMax(arr1);
System.out.println(tmp2);
}
public static int getMax(int a,int b,int c) {
//值传递
int tmp = a>b?a:b;
return c>tmp?c:tmp;
}
public static int getMax(int[] arr) {
//地址传递
arr = arr1 int max = arr[0];
for (int i=0;i<arr.length-1;i++){
if (max < arr[i+1]) {
max = arr[i+1];
}
}
return max;
}
}
public class Demo4 {
public static void main(String[] args) {
//交换两个数的值 int[] temp = {3,5};
//地址传递 jiaohuan1(temp);
//我们发现通过址传递数组temp内的两个值发生了交换
System.out.println("temp[0]:"+temp[0]+" temp[1]:"+temp[1]);// 5 3
//值传递
int[] temp1 = {3,5};
jiaohuan2(temp1[0], temp1[1]);
//通过值传递数组temp内的两个值没有发生交换
System.out.println("temp1[0]:"+temp1[0]+" temp1[1]:"+temp1[1]);// 3 5
}
//地址传递
public static void jiaohuan1(int[] arr) {
arr[0] = arr[0] ^ arr[1];
arr[1] = arr[0] ^ arr[1];
arr[0] = arr[0] ^ arr[1]; }
//值传递
public static void jiaohuan2(int a,int b) {
a = a ^ b;
b = a ^ b;
a = a ^ b;
}
}
//通过值作为参数传递,函数内部值的变量不会改变外部的值
//通过地址作为参数传递,函数内部值的变量可以直接改变外部值.
4.排序
1.排序含义
排序,即排列顺序,将数组中的元素按照一定的大小关系进行重新排列。
根据时间复杂度和空间复杂度选择排序方法 各算法的时间复杂度
平均时间复杂度 :
插入排序 O(n2)
冒泡排序 O(n2)
选择排序 O(n2)
快速排序 O(n log n)
堆排序 O(n log n)
归并排序 O(n log n)
基数排序 O(n)
希尔排序 O(n1.25)
复杂度作用:了解了时间复杂度和空间复杂度,可以更好的选择算法,提高排序查找的效率.
2.冒泡排序
import java.util.Arrays;
//冒泡排序
public class maopao {
public static void main(String[] args) {
int[] arr1= {64,42,6,2,87,38};
bubbleSort(arr1);
System.out.println("冒泡排序:"+ Arrays.toString(arr1));
}
public static void bubbleSort(int[] arr){
//控制的是一共有多少个元素
for (int i = 0; i < arr.length-1; i++) {
//确定一个元素时,进行的操作
for (int j = 0; j < arr.length-1-i; j++) {
//如果后面的元素比前面的元素小,就交换
if(arr[j] > arr[j+1]){
arr[j] ^=arr[j+1];
arr[j+1] ^=arr[j];
arr[j] ^=arr[j+1];
}
}
}
}
}
2.选择排序
import java.util.Arrays;
//选择排序
public class xuze {
public static void main(String[] args) {
int[] arr1 = {2,56,1,7,92,9,2};
selectSort(arr1);
System.out.println("选择排序:"+Arrays.toString(arr1));
}
public static void selectSort(int[] arr){
for (int i = 0; i < arr.length-1; i++) {
for (int j = i; j < arr.length-1; j++) {
//让当前的元素与后面的每一个元素对比,如果后面的比前面的小,就交换
if (arr[i] > arr[j+1]){
arr[i] ^=arr[j+1];
arr[j+1] ^=arr[i];
arr[i] ^=arr[j+1];
}
}
}
}
}
3.二分法
public class two {
public static void main(String[] args) {
/*
查找注意点:
1.当查到后,怎么处理?
查到值:返回下标 查不到:返回-1
2.当有相同的元素,怎么处理?
当查到第一个,停止查找,将第一个的下边返回
*/
int[] arr = {3,56,8,9,2};
int index = search(arr,8);
System.out.println(index);
int[] arr1 = {2,5,7,9,10};
int index1 = binarySearch(arr1,10);
System.out.println("index1:"+index1);
}
//普通查找
public static int search(int[] arr,int key){
for (int i = 0; i < arr.length; i++) {
if (arr[i] == key){
return i;
}
}
return -1;
}
//二分查找
/*
1.排序前数组必须是有序的
2.需要设置最小值,最大值,中间值
3.遍历中 h = m-1 l= m+1
4.结束条件l<=h
*/
public static int binarySearch(int[] arr,int key){
int l = 0;
int h = arr.length-1;
int m = 0;
while (l<=h){
m = (l+h)/2;
if (arr[m] == key){
return m;
}else if (arr[m] > key){
h = m-1;
}else if (arr[m] < key){
l = m+1;
}
}
//没有找到
return -1;
}
}
4.常用的方法
方法 | 描述 |
---|---|
copyOf(int[] array, int newLength) | 从原数组中拷贝指定数量的元素,到一个新的数组中,并返回这个新的数组 |
copyOfRange(int[] array, int from, int to) | 从原数组中拷贝指定范围[from,to]的元素,到一个新的数组中,并返回这个新的数组 |
equals(int[] array1, int[]array2) | 判断两个数组是否相同 |
fill(int[] array, int element) | 使用指定的数据,填充数组 |
sort(int[] array) | 对数组进行排序(升序) |
binarySearch(int[] array, int element) | 使用二分查找法,到数组中查询指定的元素出现的下标 |
toString(int[] array) | 将数组中的元素拼接成字符串返回 |
5.二维数组
public class Demo1 {
public static void main(String[] args) {
//一维数组
int[] arr = new int[3];
//二维数组
//new 后面地第一个[]中放的一维数组的个数 第二个[]中放的是一维数组的元素个数,不放就默认
int[][] arr1 = new int[2][];
//三维
int[][][] arr2 =null;
//遍历
for (int i = 0; i < arr1.length; i++) {//对应的是二维数组
for (int j = 0; j < arr1[i].length; j++) {//对应的是作为二维数组的元素的一维数组
System.out.println(arr1[i][j]);
}
}
//第一种表示方式
int[][] arr5 =new int[3][3];
arr5[0][3] = 10;
//二维数组的第二种表示形式
int[][] arr4 =new int[3][4];
arr4[0]=new int[]{2,4,7,9};
//第三种
int[][] array3 = { {1, 3}, { 2, 5}, {2, 3, 4} };
}
}
1. (易)设计一个方法,找出一个数组中最大的数字,连同所在的下标一起输出。
public static void getMax(int[] array) {
// 空数组判断
if (array == null || array.length == 0) {
System.out.println("空数组,没有元素,没有最大值");
return;
}// 1. 假设第0位的元素就是最大的
int maxElement = array[0], maxIndex = 0; 12345678
// 2. 从第1位元素开始遍历
for (int i = 1; i < array.length; i++) {
if (array[i] > maxElement) {
// 记录新的最大值
maxElement = array[i];
// 记录新的最大值下标
maxIndex = i;
}
}
// 3. 输出结果
System.out.println("数组中的最大值是: " + maxElement + ", 所在的下标 是: " + maxIndex); }
2. (中)设计一个方法,判断一个数组是不是一个升序的数组。
public static boolean checkAsc(int[] array) {
// 思路:从前往后,依次比较两个相邻的元素,如果后面的元素比前面的小,就可 以说明不是升序
for (int i = 0; i < array.length - 1; i++) {
if (array[i] > array[i + 1]) {
return false;
}
}
return true;
}
public static boolean checkAsc(int[] array) {
// 思路:递归
return checkAsc(array, array.length - 1);
}
// 判断maxIndex位元素是否比上一个元素大,并且前面的数组是否是升序
public static boolean checkAsc(int[] array, int maxIndex) {
if (maxIndex == 1) {
return array[1] > array[0];
}
return array[maxIndex] > array[maxIndex - 1] && checkAsc(array, maxIndex - 1);
}
3. (难)设计一个方法,找出一个整型数组中的第二大的值。
1. 不可以通过排序实现,不能修改数组中的数据顺序
2. 要考虑到最大的数字可能出现多次
public static int getSecondMax(int[] array) {
// 特殊情况判断
if (array == null || array.length == 0) {
System.out.println("空数组");
return -1;
}
if (array.length == 1) {
System.out.println("只有一个元素,没有次大值");
return -1;
}
// 声明两个变量,分别用来记录最大值和次大值
int max = array[0], second = array[0];
// 遍历数组中的每个元素
for (int i : array) {
if (i > max) {
// 新的最大值出现了
second = max; max = i;
}
else if (i > second && i < max) {
// 新的次大值出现了
second = i;
}
}
return second;
}
4. (中)设计一个方法,将一个数组中的元素倒序排列(注意,不是降序)。
public static void reverse(int[] array) {
// 交换第0位和最后一位,第一位和倒数第二位... 交换到一半即可
for (int i = 0; i < array.length / 2; i++) {
int temp = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - i - 1] = temp;
}
}
5. (易)将一个数组中的元素拷贝到另外一个数组中。
public static void copy(int[] src, int[] dst) {
// 1. 遍历原数组,依次将元素拷贝到目标数组中
for (int i = 0; i < src.length; i++) {
// 2. dst越界判断
if (i >= dst.length) {
break;
}
dst[i] = src[i];
}
}
6. (易)设计一个方法,比较两个数组中的元素是否相同(数量、每一个元素都相同,才
认为是相同的数组)。
public static boolean equals(int[] array1, int[] array2) {
// 特殊判断
if (array1 == null || array2 == null || array1.length != array2.length) {
return false;
}
// 逐个元素进行比较
for (int i = 0; i < array1.length; i++) {
if (array1[i] != array2[i]) {
return false;
}
}
return true;
}
7. (中)使用递归计算一个数组中的元素和。
public static int sum(int[] array) {
return sum(array, array.length - 1);
}
// 累加0~index位的元素和
public static int sum(int[] array, int index) {
if (index == 0) { return array[0];
}
return array[index] + sum(array, index - 1);
}
8.(易)小明参加歌手比赛,评委组给出10个成绩,去掉一个最高分,去掉一个最低分,求
平均分
public static double getAverage(int[] scores) {
// 1. 记录总成绩、最高成绩、最低成绩
int sum = 0, max = scores[0], min = scores[0];
// 2. 遍历所有成绩
for (int score : scores) {
// 计算总成绩
sum += score;
// 记录最高成绩
if (score > max) {
max = score;
}
// 记录最低成绩
if (score < min) {
min = score;
}
}
// 3. 计算平均成绩
return (sum - max - min) / (double)(scores.length - 2);
}
9.(中)设计一个方法,将一个字符串中的大小写字母翻转。
// 超纲知识点:
1. 将一个字符串转成一个字符数组,得到 { 'h', 'e', 'l', 'l', 'o' } char[] arr = "hello".toCharArray();
// 2. 将一个字符数组转成一个字符串,得到 "hello"
String str = new String(arr);
public static String getReverse(String str) {
// 1. 将字符串转成字符数组
char[] array = str.toCharArray();
// 2. 遍历每一位元素,大小写转换
for (int i = 0; i < array.length; i++) {
char c = array[i];
if (c >= 'a' && c <= 'z') {
array[i] -= 32;
}else if (c >= 'A' && c <= 'Z') {
array[i] += 32;
}
}
// 3. 拼接字符串返回
return new String(array);
}
10. (难)模拟实现
// System.arraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length);
public static void arraycopy(int[] src, int srcPos, int[] dst, int dstPos, int length) {
// 循环length次,进行值的拷贝
for (int i = 0; i < length; i++) {
// 越界判断
if (dstPos + i >= dst.length) {
break;
}if (srcPos + i >= src.length) {
break;
}
// 元素拷贝
dst[dstPos + i] = src[srcPos + i];
}
}
11. (易)模拟实现
//copyOf(int[] array, int newLength)
public static int[] copyOf(int[] array, int newLength) {
// 1. 实例化一个新的数组
int[] copy = new int[newLength];
// 2. 依次将原数组中的元素拷贝到新的数组中
for (int i = 0; i < newLength; i++) {
if (i >= array.length) {
break;
}
copy[i] = array[i];
}
return copy;
}
12. (易)模拟实现
String toString(int[] array)
public static int[] copyOf(int[] array, int newLength) {
// 1. 实例化一个新的数组
int[] copy = new int[newLength];
// 2. 依次将原数组中的元素拷贝到新的数组中
for (int i = 0; i < newLength; i++) {
if (i >= array.length) {
break;
}
copy[i] = array[i];
}
return copy;
}
13. (难)已知方法 public static int[] combine(int[] arr1, int[] arr2) 的作用是,合并两个数
组,并对合并后的数组进行升序排序,返回这个数组。实现这个方法。
public static int[] combine(int[] arr1, int[] arr2) {
// 1. 合并数组
int[] combine = Arrays.copyOf(arr1, arr1.length + arr2.length);
System.arraycopy(arr2, 0, combine, arr1.length, arr2.length);
// 2. 排序
Arrays.sort(combine);
return combine;
}
14(难)已知方法 public static int[] delete(int[] arr, int ele) 的作用是删除数组中第一次出
现的ele元素,并返回删除后的数组。实现这个方法。
public static int[] delete(int[] array, int element) {
// 1. 计算下标
int index = -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == element) {
index = i;
break;
}
}
// 2. 判断不存在
if (index == -1) {
return array;
}
// 3. 用后面的元素覆盖前面的
System.arraycopy(array, index + 1, array, index, array.length - index - 1);
return Arrays.copyOf(array, array.length - 1);
}