数值型数组特征值统计:
简单示例:
求总和与均值:
给定数组arr = {4,5,6,1,9},求其总和、平均值并输出。
求解代码:
public class Test { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //求总和、均值 int sum = 0;//因为0加上任何数都不影响结果 for(int i=0; i<arr.length; i++){ sum += arr[i];//求总和 } double avg = (double)sum/arr.length;//求平均值 System.out.println("sum = " + sum);//输出总和 System.out.println("avg = " + avg);//输出平均值 } }
最大最小值:
给定数组arr = {4,5,6,1,9},求其最大最小值并输出。
求解代码:
public class Test { public static void main(String[] args) { int[] arr = {4,5,6,1,9}; //找最大值 int max = arr[0]; //此处i从1开始,若是max则不需要与arr[0]再比较一次了 for(int i=1; i<arr.length; i++){ if(arr[i] > max){ max = arr[i]; } } int min = arr[0]; //此处i从1开始,若是min则不需要与arr[0]再比较一次了 for(int i=1; i<arr.length; i++){ if(arr[i] < min){ min = arr[i]; } } System.out.println("max = " + max); System.out.println("min = " + min); } }
复制、赋值
使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。
public class ArrayExer04 { public static void main(String[] args) { //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。 int[] array1,array2; //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。 array1 = new int[]{2,3,5,7,11,13,17,19}; //(3)显示array1的内容。 for (int i = 0; i < array1.length; i++) { System.out.print(array1[i] + "\t"); } //(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。 array2 = array1; System.out.println(); System.out.println(array1); System.out.println(array2); for (int i = 0; i < array2.length; i++) { if(i % 2 == 0){ array2[i] = i; } } System.out.println();//换行 //(5)打印出array1。 for (int i = 0; i < array1.length; i++) { System.out.print(array1[i] + "\t"); } } }
思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。
拓展:修改题目,实现array2对array1数组的复制
public class ArrayExer04_1 { public static void main(String[] args) { //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。 int[] array1,array2; //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。 array1 = new int[]{2,3,5,7,11,13,17,19}; //(3)显示array1的内容。 for (int i = 0; i < array1.length; i++) { System.out.print(array1[i] + "\t"); } //(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。 array2 = new int[array1.length]; for (int i = 0; i < array1.length; i++) { array2[i] = array1[i]; } System.out.println(); System.out.println(array1); System.out.println(array2); for (int i = 0; i < array2.length; i++) { if(i % 2 == 0){ array2[i] = i; } } System.out.println();//换行 //(5)打印出array1。 for (int i = 0; i < array1.length; i++) { System.out.print(array1[i] + "\t"); } } }
数组扩容
现有数组 int[] arr = new int[]{1,2,3,4,5};
现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?
public class ArrayExer01_1 { public static void main(String[] args) { int[] arr = new int[]{1,2,3,4,5}; //扩容1倍容量 // int[] newArr = new int[arr.length * 2]; //或 int[] newArr = new int[arr.length << 1]; //将原有数组中的元素复制到新的数组中 for (int i = 0; i < arr.length; i++) { newArr[i] = arr[i]; } //将10,20,30三个数据添加到新数组中 newArr[arr.length] = 10; newArr[arr.length + 1] = 20; newArr[arr.length + 2] = 30; //将新的数组的地址赋值给原有的数组变量 arr = newArr; //遍历arr for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
数组缩容
现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。
public class ArrayExer01_2 { public static void main(String[] args) { int[] arr={1,2,3,4,5,6,7}; int deleteIndex = 4; //方式1:不新建数组 // for(int i = deleteIndex;i < arr.length - 1;i++){ // arr[i] = arr[i + 1]; // } // // //修改最后元素,设置为默认值 // arr[arr.length - 1] = 0; //方式2:新建数组,新的数组的长度比原有数组的长度少1个 int[] newArr = new int[arr.length - 1]; for (int i = 0; i < deleteIndex; i++) { newArr[i] = arr[i]; } for(int i = deleteIndex;i < arr.length - 1;i++){ newArr[i] = arr[i + 1]; } arr = newArr; //遍历arr数组 for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
较难示例:
找出给定数组中包含的最大子数组:
public class Test { public static void main(String[] args) { int[] arr = new int[]{1, -2, 3, 10, -4, 7, 2, -5}; int i = getGreatestSum(arr); System.out.println(i); // 应输出 18 } public static int getGreatestSum(int[] arr){ int greatestSum = 0; // 初始化最大和为0 if(arr == null || arr.length == 0){ // 检查数组是否为空 return 0; // 如果数组为空,返回0 } int temp = greatestSum; // 初始化临时和为0 for(int i = 0; i < arr.length; i++){ // 遍历数组 temp += arr[i]; // 将当前元素加到临时和上 if(temp < 0){ // 如果临时和小于0,重置为0 temp = 0; } if(temp > greatestSum){ // 如果临时和大于最大和,更新最大和 greatestSum = temp; } } if(greatestSum == 0){ // 如果最大和仍然是0,说明数组中所有元素都是负数 greatestSum = arr[0]; // 初始化最大和为第一个元素 for(int i = 1; i < arr.length; i++){ // 再次遍历数组,找到最大的单个元素 if(greatestSum < arr[i]){ // 如果当前元素大于最大和,更新最大和 greatestSum = arr[i]; } } } return greatestSum; // 返回最大和 } }
数组数值赋值:
使用二维数组打印一个10行杨辉三角:
分析:
-
-
每一行的第一个元素和最后一个元素都是 1
-
从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];
求解代码:
public class Test { public static void main(String[] args) { //1. 动态初始化的方式创建二维数组 int[][] yangHui = new int[10][]; for (int i = 0; i < yangHui.length; i++) { yangHui[i] = new int[i + 1]; //2. 给数组元素赋值 // 2.1 给外层数组元素中的首元素和末元素赋值 yangHui[i][0] = yangHui[i][i] = 1; //2.2 给外层数组元素中的非首元素和非末元素赋值(难) //非首元素和非末元素的角标范围 for(int j = 1;j < yangHui[i].length - 1;j++){ yangHui[i][j] = yangHui[i-1][j-1] + yangHui[i-1][j]; } } //3. 遍历二维数组 for (int i = 0; i < yangHui.length; i++) { for (int j = 0; j < yangHui[i].length; j++) { System.out.print(yangHui[i][j] + "\t"); } System.out.println(); } } }
生成一个数组:
创建一个长度为6的int型数组,要求数组元素的值都在1-30之间,且是随机赋值。同时,要求元素的值各不相同。
求解代码:
public class Test { public static void main(String[] args) { int[] arr = new int[6]; for (int i = 0; i < arr.length; i++) { arr[i] = new Random().nextInt(1,30); for (int j = 0; j < i; j++) { if (arr[i] == arr[j]) { i--; break; } } } for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } } }
回形数
例如:
输入数字2,则程序输出:
1 2
4 3
输入数字3,则程序输出:
1 2 3
8 9 4
7 6 5
输入数字4, 则程序输出:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
实现代码:
方式一:
public class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("输入一个数字"); int len = scanner.nextInt(); int[][] arr = new int[len][len]; int s = len * len; /* * k = 1:向右 * k = 2:向下 * k = 3:向左 * k = 4:向上 */ int k = 1; int i = 0,j = 0; for(int m = 1;m <= s;m++){ if(k == 1){ if(j < len && arr[i][j] == 0){ arr[i][j++] = m; }else{ k = 2; i++; j--; m--; } }else if(k == 2){ if(i < len && arr[i][j] == 0){ arr[i++][j] = m; }else{ k = 3; i--; j--; m--; } }else if(k == 3){ if(j >= 0 && arr[i][j] == 0){ arr[i][j--] = m; }else{ k = 4; i--; j++; m--; } }else if(k == 4){ if(i >= 0 && arr[i][j] == 0){ arr[i--][j] = m; }else{ k = 1; i++; j++; m--; } } } //遍历 for(int m = 0;m < arr.length;m++){ for(int n = 0;n < arr[m].length;n++){ System.out.print(arr[m][n] + "\t"); } System.out.println(); } } }
方式二:
public class Test { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); System.out.println("输入一个数字"); int n = scanner.nextInt(); int[][] arr = new int[n][n]; //要显示的数据 int count = 0; //x轴的最大下标 int maxX = n-1; //Y轴的最大下标 int maxY = n-1; //x轴的最小下标 int minX = 0; //Y轴的最小下标 int minY = 0; while(minX<=maxX) { for(int x=minX;x<=maxX;x++) { arr[minY][x] = ++count; } minY++; for(int y=minY;y<=maxY;y++) { arr[y][maxX] = ++count; } maxX--; for(int x=maxX;x>=minX;x--) { arr[maxY][x] = ++count; } maxY--; for(int y=maxY;y>=minY;y--) { arr[y][minX] = ++count; } minX++; } for(int i=0;i<arr.length;i++) { for(int j=0;j<arr.length;j++) { String space = (arr[i][j] + "").length()==1 ? "0":""; System.out.print(space + arr[i][j] + " "); } System.out.println(); } } }
数组数值反转:
数组对称位置的元素互换。
实现代码:
方法一:
public class Test { public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println("反转之前:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } System.out.println(); //反转 /* 思路:首尾对应位置的元素交换 (1)确定交换几次 次数 = 数组.length / 2 (2)谁和谁交换 for(int i=0; i<次数; i++){ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } */ for(int i=0; i<arr.length/2; i++){ int temp = arr[i]; arr[i] = arr[arr.length-1-i]; arr[arr.length-1-i] = temp; } System.out.println("反转之后:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
方法二:
public class Test { public static void main(String[] args) { int[] arr = {1,2,3,4,5}; System.out.println("反转之前:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } System.out.println(); //反转 //左右对称位置交换 for(int left=0,right=arr.length-1; left<right; left++,right--){ //首 与 尾交换 int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; } System.out.println("反转之后:"); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
字符串反转:
将字符串转换为字符数组进行反转
写法一:使用char数组,双循环变量
public void test() { String str = "abcdefg"; System.out.println(str); char[] strToCharArray = str.toCharArray(); for (int i = 0, j = strToCharArray.length - 1; i < j; i++, j--) { char temp = strToCharArray[i]; strToCharArray[i] = strToCharArray[j]; strToCharArray[j] = temp; } System.out.println(); str = String.valueOf(strToCharArray); System.out.println(str); }
写法二:使用char数组,单循环变量
public void test() { String str = "abcdefg"; System.out.println(str); char[] strToCharArray = str.toCharArray(); int half = (int) Math.floor(strToCharArray.length / 2); for (int i = strToCharArray.length - 1; i >= half; i--) { char temp = strToCharArray[strToCharArray.length - i - 1]; strToCharArray[strToCharArray.length - i - 1] = strToCharArray[i]; strToCharArray[i] = temp; } System.out.println(); str = String.valueOf(strToCharArray); System.out.println(str); }
使用异或运算符(^)来实现反转
public void test() { String str = "abcdefg"; System.out.println(str); char[] strToCharArray = str.toCharArray(); int half = (int) Math.floor(strToCharArray.length / 2); for (int i = 0; i < half; i++) { strToCharArray[i] ^= strToCharArray[strToCharArray.length - i - 1]; strToCharArray[strToCharArray.length - i - 1] ^= strToCharArray[i]; strToCharArray[i] ^= strToCharArray[strToCharArray.length - i - 1]; } System.out.println(); str = String.valueOf(strToCharArray); System.out.println(str); }
使用StringBuilder类的reverse()来实现反转
public void test() { String str = "abcdefg"; StringBuilder stringBuilder = new StringBuilder(str); System.out.println(stringBuilder); String s = String.valueOf(stringBuilder.reverse()); System.out.println(s); }
排序:
冒泡排序:
使用冒泡排序,实现整型数组元素的排序操作
比如:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
public class BubbleSortTest { public static void main(String[] args) { int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67}; //遍历 for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } //冒泡排序,实现数组元素从小到大排列 for(int j = 0;j < arr.length - 1;j++){ for (int i = 0; i < arr.length - 1 - j; i++) { if(arr[i] > arr[i + 1]){ //交互arr[i] 和 arr[i + 1] int temp = arr[i]; arr[i] = arr[i + 1]; arr[i + 1] = temp; } } } System.out.println(); for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + "\t"); } } }
快速排序:
使用快速排序,实现整型数组元素的排序操作
比如:int[] data = { 9, -16, 30, 23, -30, -49, 25, 21, 30 };
public class QuickSort { public static void main(String[] args) { int[] data = {9, -16, 30, 23, -30, -49, 25, 21, 30}; System.out.println("排序之前:"); for (int i = 0; i < data.length; i++) { System.out.print(data[i]+" "); } quickSort(data);//调用实现快排的方法 System.out.println("\n排序之后:"); for (int i = 0; i < data.length; i++) { System.out.print(data[i]+" "); } } public static void quickSort(int[] data) { subSort(data, 0, data.length - 1); } private static void subSort(int[] data, int start, int end) { if (start < end) { int base = data[start]; int low = start; int high = end + 1; while (true) { while (low < end && data[++low] - base <= 0){ } while (high > start && data[--high] - base >= 0){ } if (low < high) { //交换data数组[low]与[high]位置的元素 swap(data, low, high); } else { break; } } //交换data数组[start]与[high]位置的元素 swap(data, start, high); //经过代码[start, high)部分的元素 比[high, end]都小 //通过递归调用,对data数组[start, high-1]部分的元素重复刚才的过程 subSort(data, start, high - 1); //通过递归调用,对data数组[high+1,end]部分的元素重复刚才的过程 subSort(data, high + 1, end); } } private static void swap(int[] data, int i, int j) { int temp = data[i]; data[i] = data[j]; data[j] = temp; } }
数组工具类Arrays的使用
public class ArraysTest { public static void main(String[] args) { //1. boolean equals(int[] a,int[] b):比较两个数组的元素是否依次相等 int[] arr1 = new int[]{1,2,3,4,5}; int[] arr2 = new int[]{1,2,3,4,5}; arr2 = new int[]{1,2,3,5,4}; System.out.println(arr1 == arr2); boolean isEquals = Arrays.equals(arr1,arr2); System.out.println(isEquals);//true ---> false //2. String toString(int[] a):输出数组元素信息。 System.out.println(arr1); //[I@776ec8df System.out.println(Arrays.toString(arr1)); //3.void fill(int[] a,int val):将指定值填充到数组之中。 Arrays.fill(arr1,10); System.out.println(Arrays.toString(arr1)); //4. void sort(int[] a):使用快速排序算法实现的排序 int[] arr3 = new int[]{34,54,3,2,65,7,34,5,76,34,67}; Arrays.sort(arr3); System.out.println(Arrays.toString(arr3)); //5. int binarySearch(int[] a,int key):二分查找 //使用前提:当前数组必须是有序的 int index = Arrays.binarySearch(arr3,15); if(index >= 0){ System.out.println("找到了,索引位置为:" + index); }else{ System.out.println("未找到"); } } }
数组的使用中常见的异常:
public class ArrayExceptionTest { public static void main(String[] args) { // 1. 数组角标越界的异常: int[] arr = new int[10]; //角标的有效范围:0、1、2、...、9 // System.out.println(arr[10]); // System.out.println(arr[-1]); // 2. 空指针异常: //情况1: // int[] arr1 = new int[10]; // // arr1 = null; // // System.out.println(arr1[0]);//NullPointerException //情况2: // int[][] arr2 = new int[3][]; // //// arr2[0] = new int[10];//此行代码不存在时,下一行代码出现NullPointerException // // System.out.println(arr2[0][1]); //NullPointerException //情况3: // String[] arr3 = new String[4]; // System.out.println(arr3[0].toString());//NullPointerException } }
查找:
顺序查找:
public class LinearSearchTest { public static void main(String[] args) { int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67}; int target = 5; // target = 15; //查找方式:线性查找 //方式1: // boolean isFlag = true; // for(int i = 0;i < arr1.length;i++){ // if(target == arr1[i]){ // System.out.println("找到了" + target + ",对应的位置为:" + i); // isFlag = false; // break; // } // } // // if(isFlag){ // System.out.println("未找到此元素!"); // } //方式2: int i = 0; for(;i < arr1.length;i++){ if(target == arr1[i]){ System.out.println("找到了" + target + ",对应的位置为:" + i); break; } } if(i == arr1.length){ System.out.println("未找到此元素!"); } } }
优点:
算法逻辑简单;
缺点:
执行效率低,时间复杂度为O(n);
二分查找:
public class BinarySearchTest { public static void main(String[] args) { int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100}; int target = 5; // target = 17; int head = 0;//默认的首索引 int end = arr2.length - 1;//默认的尾索引 boolean isFlag = false;//判断是否找到了指定元素 while(head <= end){ int middle = (head + end) / 2; if(target == arr2[middle]){ System.out.println("找到了" + target + ",对应的位置为:" + middle); isFlag = true; break; }else if(target > arr2[middle]){ head = middle + 1; }else{//target < arr2[middle] end = middle - 1; } } if(!isFlag){ System.out.println("未找到该元素"); } } }
优点:
执行效率高,时间复杂度为O(logN);
缺点:
逻辑稍复杂,数组必须有序;