Java数组经典例题
文章目录
前言
这篇博客是记录在学完Java数组后,对于一些与数组操作相关的经典例题的记录。
一、杨辉三角形
1.1 杨辉三角形的特性
- 他的两条斜边都是数字1组成,其余的数等于他肩上的两数之和
- 每行数字左右对称,由1开始,逐渐增大
- 第n行的数字个数为n
- 第n行的数字之和为2^n-1;
1.2 解题思路
- 每一行的行首和行尾均为1,其他均为他肩上的两数之和,可以按照这两个特点将其分为两个部分赋值;第一部分先给首末元素赋值,然后再在第二部分给非首末元素赋值。
- 关键:给非首末元素赋值
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
1.3 完整代码
public static void pascalTri() {
//1.声明并初始化二维数组
int[][] arr = new int[10][];
//2.给二维数组赋值
for(int i = 0; i<arr.length; i++) {
//2.1初始化
arr[i] = new int[i + 1];
//2.2给首末元素赋1
arr[i][0] = arr[i][i] = 1;
//2.3给非首末元素赋值
for(int j = 1; j < arr[i].length - 1; j++) {
arr[i][j] = arr[i-1][j-1] + arr[i-1][j];
}
}
//3.遍历二维数组
for(int i = 0; i < arr.length; i++) {
System.out.format("%" + (arr.length-i) + "s", " "); //输出空格字符串
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
二、回形数
2.1 题目描述
- 从键盘输入一个整数(1~20);则以该数字为矩阵的大小,把1,2,3…n*n 的数字按照顺时针螺旋的形式填入其中。
- 例如:
- 输入数字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
- 输入数字2,则程序输出:
2.2 解题思路
- 对于回形数的特点,不难观察出它只存在向右、向下、向左、向上四个方向的运动,不管题目要求的是赋值还是打印,都只有这四个方向,所以只需要对二维数组的下标进行操作,当达到当前边界时,转换方向继续遍历。
2.3 完整代码
- 代码相对显得的繁琐,有4个if判断,但是理解起来较为简单直观,若要简化代码,可以将二维数据下标的变化也初始化为一个二维数组:(1, 0), (0, 1), (-1, 0), (0, -1);具体实现可以自己尝试。
public static void numberLoops() {
Scanner scan = new Scanner(System.in);
System.out.print("输入方阵大小:");
int len = scan.nextInt();
int[][] arr = new int[len][len];
int sum = len * len; //计数,用于跳出循环
//关键: k=1:right; k=2:down; k=3:left; k=4:up
int k = 1; //先向右开始
int i = 0, j = 0;
for (int m = 1; m <= sum; m++) {
if(k == 1) { //向右
if(j < len && arr[i][j] == 0) {
arr[i][j++] = m; //当前行向右
}else {
k = 2; //向右转向向下
i++; //向下一行
j--; //因为最后一次j++,j会超出当前边界,j--回到边界
m--; //不满足当前方向会退出本次循环,m+1, 退回到不符合当前方向的m
}
}else if(k == 2) { //向下
if(i < len && arr[i][j] == 0) {
arr[i++][j] = m; //当前列向下
}else {
k = 3; //向下转向向左
i--; //因为最后一次i++,i会超出当前边界,i--回到边界
j--; //当前行向左
m--; //不满足当前方向会退出本次循环,m+1, 退回到不符合当前方向的m
}
}else if(k == 3) { //向左
if(j >= 0 && arr[i][j] == 0) {
arr[i][j--] = m; //当前行向左
}else {
k = 4; //向左转向向上
i--; //向上一行
j++; //因为最后一次j--,j会超出当前边界,j++回到边界
m--; //不满足当前方向会退出本次循环,m+1, 退回到不符合当前方向的m
}
}else if(k == 4) { //向上
if(i >= 0 && arr[i][j] == 0) {
arr[i--][j] = m; //当前列向上
}else {
k = 1; //向上转向向右
i++; //因为最后一次i--,i会超出当前边界,i--回到边界
j++; //向下
m--; //不满足当前方向会退出本次循环,m+1, 退回到不符合当前方向的m
}
}
}
三、数组的基本操作
3.1 数组的复制
- for循环复制
int[] arrCopy = new int[arr.length]; for(int i = 0; i < arr.length; i++) { arrCopy[i] = arr[i]; }
3.2 数组的反转
- 经典三段式交换两个数的值
for(int i = 0; i < arr.length/2; i++) { int temp = arr[i]; arr[i] = arr[arr.length-i-1]; arr[arr.length-i-1] = temp; }
3.3 数组的查找
- (1)线性查找
//线性查找 int x = 5; //待查找数 boolean isFlag = true; for (int i = 0; i < arr.length; i++) { if(arr[i] == x) { System.out.println("线性查找成功!索引值为:" + i); isFlag = false; break; } } if(isFlag) { System.out.println("未找到。"); }
- (2)二分查找
//二分查找(前提数组有序) int xx = 7; int low = 0; int high = arr.length - 1; int mid = 0; boolean isFlag1 = true; while(low <= high) { mid = (low + high) / 2; if(xx == arr[mid]){ System.out.println("二分查找成功!索引值为:" + mid); isFlag1 = false; break; }else if(xx > arr[mid]) { low = mid + 1; }else { high = mid - 1; } } if(isFlag1) { System.out.println("未找到。"); }
四、排序算法
4.1 最简单的排序:冒泡排序
- 下面贴代码
public static void arraySorted() {
int[] arr = new int[]{43, 32, 76, -98, 5, 64, 13};
//冒泡排序
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr.length-i-1; j++) {
if(arr[j] > arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//遍历数组
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
4.2 最需要掌握的排序:快速排序
- 快排的主要思想就是不断的从表的两端向中间进行扫描,将小的放到左边,大的放到右边,作为标准的元素放到中间,在将两边的子表作为下一次快排的主表,重复执行,直到排序完成。
- 下面贴代码
/**
* 快排入口函数
* @param arr 待排序数组
* @param low 数组起始
* @param high 数组末尾
*/
public static void quickSort(int[] arr, int low, int high) {
if(low < high) { //low==high 循环调出条件
int pivotpos = qkSortPart(arr, low, high); //第一趟快排
quickSort(arr, low, pivotpos-1); //递归快排pivot分界左边部分
quickSort(arr, pivotpos+1, high); //递归快排pivot分界右边部分
}
}
/**
* 快速排序的核心部分
* @param arr 待排序数组
* @param low 数组起始
* @param high 数组末尾
* @return 一趟快排后数组的分界数
*/
public static int qkSortPart(int[] arr, int low, int high) {
int pivot = arr[low]; //快排的枢轴
while(low < high) {
while(low < high && arr[high] >= pivot) --high; //hign从右往左找小于pivot的数
arr[low] = arr[high]; //将比pivot小的数放到其左边
while(low < high && arr[low] <= pivot) ++low; //low从左往右找大于pivot的数
arr[high] = arr[low]; //将比pivot大的数放在其右边
}
arr[low] = pivot; //将枢轴放到最终分界位置
return low; //返回这个分界位置
}
总结
以上就是在学习Java数组过程中遇见的经典例题,其中数组的查找和排序十分重要,这里排序只写了冒泡和快排,后续也会专门写一遍关于十大排序算法的博客,夯实数组的相关基础。