相信很多同行小伙伴会因为许多原因想跳槽,不论是干得不开心还是想跳槽涨薪,在如此内卷的行业,我们都面临着“面试造火箭,上班拧螺丝”的局面,鉴于当前形势博主呕心沥血整理的干货满满的造火箭的技巧来了,本博主花费2个月时间,整理归纳java全生态知识体系常见面试题!总字数高达百万! 干货满满,每天更新,关注我,不迷路,用强大的归纳总结,全新全细致的讲解来留住各位猿友的关注,希望能够帮助各位猿友在应付面试笔试上!当然如有归纳总结错误之处请各位指出修正!如有侵权请联系博主QQ1062141499!
目录
1 JAVA中数组扩容的三种方式
2 冒泡排序(Bubble Sort)
3 插入排序(Insertion Sort)
4 选择排序(Selection Sort)
5 希尔排序(Shell Sort)
6 递归阶乘
7 ??????使用递归输出某个目录下所有子目录和文件
1 JAVA中数组扩容的三种方式
① int[] arr2=new int[arr1.length*2] //新数组长度for(int i=0;i<arr1.length;i++){ //复制arr2[i]=arr1[i];}② int[] arr2=java.util.Arrays.copyOf(原数组名,新数组长度);③ int[] arr2=new int[arr1.length*2]System.arraycopy(原数组名,起始下标,新数组名,起始下标,复制长度);
2 冒泡排序(Bubble Sort)
冒泡排序是一种简单的排序算法。
步骤:
- 遍历比较相邻的两个元素,被比较的左边元素大于右边元素,则交换位置。第一轮遍历、比较、交换完,最后一个是最大的元素
- 若本次遍历中没有数据交换,代表排序结束,提前退出
- 有数据交换则再从第一个元素开始遍历、比较、交换,排除最后一个元素
- 重复 1、2、3 步骤,每次排除上次被遍历的最后一个元素,直到排序完成
public static void main(String[] args) {int[] ints = {3, 4, 23, 11, 0, 3, 4};bubbleSort(ints);}/*** 冒泡排序算法* 只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。* 如果不满足就让它俩互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n 次,* 就完成了 n 个数据的排序工作。**/private static void bubbleSort(int[] ints) {//临时交换的数据int temp;for (int i = 0; i < ints.length; i++) {//j<ints.length-i-1,因为冒泡是把每轮循环中较大的数飘到后面for (int j = 0; j < ints.length - i - 1; j++) {if (ints[j] > ints[j + 1]) {temp = ints[j];ints[j] = ints[j + 1];ints[j + 1] = temp;}}System.out.println(Arrays.toString(ints));}}
打印结果:
[3, 4, 11, 0, 3, 4, 23]
[3, 4, 0, 3, 4, 11, 23]
[3, 0, 3, 4, 4, 11, 23]
[0, 3, 3, 4, 4, 11, 23]
[0, 3, 3, 4, 4, 11, 23]
[0, 3, 3, 4, 4, 11, 23]
[0, 3, 3, 4, 4, 11, 23]
3 插入排序(Insertion Sort)
思路:
- 将数组分为两个区域:已排序、未排序。
- 初始已排序区域只第一个元素
- 取未排序的区域的元素,在已排序的区域找到合适的位置插入
- 保证已排序区域的数据一直有序
- 重复这个过程,直到未排序区域为空
步骤:
- 从数组第二个数开始,往后逐个取数,跟前面的数进行比较
- 当所取的数,比前面的数大,停止比较,取一下个进行比较
- 当所取的数,比前面的数小,把比所取数大的数都往后挪一个,直到所取数大于被比较的数停止,最后把所取数插入到比它小的数的右边
代码:
public static void main(String[] args) {int[] ints = {3, 4, 23, 11, 0, 3, 4};insertionSort(ints);}/*** 插入排序*/private static void insertionSort(int[] ints) {for (int i = 1; i <ints.length; i++) {int j = i - 1;int value = ints[i];for (; j >= 0; j--) {if (ints[j] > value) {ints[j+1] = ints[j];} else {break;}}ints[j+1] = value;System.out.println(Arrays.toString(ints));}}
}
打印
[3, 4, 23, 11, 0, 3, 4]
[3, 4, 23, 11, 0, 3, 4]
[3, 4, 11, 23, 0, 3, 4]
[0, 3, 4, 11, 23, 3, 4]
[0, 3, 3, 4, 11, 23, 4]
[0, 3, 3, 4, 4, 11, 23]
特征:
- 最好情况时间复杂度:O(n) 。即数组本身有序,如 1,2,3,4,5
- 最坏情况时间复杂度:O(n2) 。即数组本身完全逆序,如 5,4,3,2,1
- 平均时间复杂度:O(n2) 。在数组中插入一个数据的平均时间复杂度是 O(n),插入排序执行 n 次往数组中插入操作,所以平均时间复杂度是 O(n2)
- 空间复杂度是 O(1)。是原地排序
- 可以保持相等的值原有的前后顺序不变,是稳定排序
4 选择排序(Selection Sort)
思路:
- 数组区分已排序区域和未排序区域
- 每次从未排序区域找到最小的元素,通过和未排序区域第一个元素交换位置,把它放到已排序区域的末尾
步骤:
- 进行 数组长度-1 轮比较
- 每轮找到未排序区最小值的小标
- 如果最小值的下标非未排序区第一个,进行交换。此时未排序区第一个则变为已排序区最后一个
- 进行下一轮找未排序区最小值下标,直到全部已排序
代码:
public static void main(String[] args) {int[] ints = {3, 4, 23, 11, 0, 3, 4};selectionSort(ints);
}
/*** 选择排序*/
public static void selectionSort(int[] ints) {//进行 数组长度-1 轮比较int minIndex;for (int i = 0; i < ints.length - 1; i++) {minIndex = i;//取未排序区第一个数的下标for (int j = i + 1; j < ints.length; j++) {if (ints[j] < ints[minIndex]) {//找到未排序区域最小值的下标minIndex = j;}}//找到的最小值是否需要挪动if (i != minIndex) {int temp = ints[i];ints[i] = ints[minIndex];ints[minIndex] = temp;}System.out.println(Arrays.toString(ints));}
}
打印
[0, 4, 23, 11, 3, 3, 4]
[0, 3, 23, 11, 4, 3, 4]
[0, 3, 3, 11, 4, 23, 4]
[0, 3, 3, 4, 11, 23, 4]
[0, 3, 3, 4, 4, 23, 11]
[0, 3, 3, 4, 4, 11, 23]
特征:
- 空间复杂度为 O(1),是原地排序算法
- 最好情况时间复杂度为 O(n2)。即使是有序数组,也需要经过 n-1 轮找未排序区最小值下标
- 最坏情况时间复杂度为 O(n2)
- 平均情况时间复杂度为 O(n2)
- 非稳定排序,即排序后不能保证两个相等值的前后顺序未变。如:4,8,4,2,9。第一轮找到最小元素 2,跟第一个 4 交换位置,直到排序完成第一个 4 排在第二个 4 后面
5 希尔排序(Shell Sort)
插入排序经过改进之后的高效版本,也称缩小增量排序。1959 年提出,是突破时间复杂度 O(n2) 的第一批算法之一。缩小增量排序的最优增量选择是一个数学难题,一般采用希尔建议的增量,具体如下。
思路与步骤:
- 首次选择的增量(即步长,下同) step = 数组长度 / 2 取整;缩小增量 step? ,每次减半,直到为 1 结束缩小;逐渐缩小的增量组成一个序列:[n/2, n/2/2, ... 1]
- 对数组进行 序列里增量的个数 趟排序
- 每趟排序,把增量作为间隔,将数组分割成若干子数组,分别对各子数组进行插入排序
- 当增量等于 1 时,排序整个数组后,排序完成
代码:
public static void main(String[] args) {int[] ints = {3, 4, 23, 11, 0, 3, 4};selectionSort(ints);
}
/*** 希尔排序*/
private static void shellSort(int[] ints) {int length = ints.length;int step = length / 2; //步长,默认取数组长度一半int temp;while (step > 0) {for (int i = step; i < length; i++) { //从步长值为下标,开始遍历temp = ints[i]; //当前值int preIndex = i - step; //步长间隔上一个值的下标//在步长间隔的的数组中,找到需要插入的位置,挪动右边的数while (preIndex >= 0 && ints[preIndex] > temp) {ints[preIndex + step] = ints[preIndex];preIndex -= step;}//把当前值插入到在步长间隔的的数组中找到的位置ints[preIndex + step] = temp;}step /= 2;System.out.println(Arrays.toString(ints));}
}
打印
[3, 0, 23, 6, 4, 33, 11]
[0, 3, 4, 6, 11, 23, 33]
特征:
- 空间复杂度为 O(1),是原地排序算法
- 最好、最坏、平均情况时间复杂度,都是 O(nlog2 n)
- 非稳定排序。因为进行了增量间隔分组排序,可能导致相等的值先后顺序变换
6 递归阶乘
n!=1×2×3×...×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
亦即n!=1×2×3×...×n。阶乘亦可以递归方式定义:0!=1,n!=(n-1)!×n。
如5的阶乘为1*2*3*4*5=120,用代码实现如下:
public static void main(String[] args) {System.out.println(recursionN(5));
}
/*** 递归计算n的阶乘* @param n* @return*/
private static int recursionN(int n) {if (n <1) {throw new IllegalArgumentException("参数必须大于0");} else if (n == 1) {return 1;} else {return n * recursionN(n - 1);}
}
7 ??????使用递归输出某个目录下所有子目录和文件
public static void main(String[] args) {print(new File("E:/"));
}
private static void print(File file) {System.out.println(file.getAbsolutePath());if (file.isDirectory()) {File[] files = file.listFiles();for (File f : files) {print(f);}}
}