相信很多同行小伙伴会因为许多原因想跳槽,不论是干得不开心还是想跳槽涨薪,在如此内卷的行业,我们都面临着“面试造火箭,上班拧螺丝”的局面,鉴于当前形势博主呕心沥血整理的干货满满的造火箭的技巧来了,本博主花费2个月时间,整理归纳java全生态知识体系常见面试题!总字数高达百万! 干货满满,每天更新,关注我,不迷路,用强大的归纳总结,全新全细致的讲解来留住各位猿友的关注,希望能够帮助各位猿友在应付面试笔试上!当然如有归纳总结错误之处请各位指出修正!如有侵权请联系博主QQ1062141499!
目录
1 什么是递归?递归的优缺点是什么?
2 什么是复杂度?为什么要进行复杂度分析?
3 什么是时间复杂度?什么是空间复杂度?
4 如何进行复杂度分析?
5 O(1), O(n), O(n2), O(logn), O(nlogn) 的区别
6 常见加密算法有哪些?是否对称?
7 数组与链表的区别
8 同样的复杂度,为什么插入排序比冒泡排序更受欢迎?
递归:直接或间接调用自身算法的过程
满足使用递归的条件:
优点:
缺点:
复杂度
为什么要进行复杂度分析?
时间复杂度分析:
1、大 O 复杂度表示法:T(n) = O(f(n)),公式中的 O,表示代码的执行时间 T(n) 与 f(n) 表达式成正比
2、最好情况时间复杂度:代码在最理想情况下执行的时间复杂度
3、最坏情况时间复杂度:代码在最坏情况下执行的时间复杂度
4、平均时间复杂度:代码在所有情况下执行的次数的加权平均值
5、均摊时间复杂度:极少数高级别复杂度且发生具有时序关系时,可以将这几个高级别的复杂度均摊到低级别复杂度上,一般均摊结果就等于低级别复杂度
空间复杂度分析:
常见的复杂度:
在描述算法复杂度时,经常用到O(1), O(n), O(logn), O(nlogn)来表示对应复杂度程度, 不过目前大家默认也通过这几个方式表示空间复杂度 。
那么,O(1), O(n), O(logn), O(nlogn)就可以看作既可表示算法复杂度,也可以表示空间复杂度。
大O加上()的形式,里面其实包裹的是一个函数f(),O(f()),指明某个算法的耗时/耗空间与数据增长量之间的关系。其中的n代表输入数据的量。
如果ax=N(a>0,且a≠1),那么数x叫做以a为底N的对数,记作x=logaN,读作以a为底N的对数,其中a叫做对数的底数,N叫做真数。
前面了解了 冒泡排序 和 插入排序,时间复杂度、空间复杂度都相同:
但为什么实际开发中插入排序使用偏多呢?
原因如下:
代码对比:
//冒泡排序 int temp = array[j + 1]; array[j+1] = array[j]; array[j] = temp; hasSwitch = true;//有数据交换 //插入排序 if (array[j] > value) { array[j+1] = array[j]; } else { break; }
测试代码:
package Lee.interview.algorithm; import java.util.Random; /** * 测试冒泡排序 * @author Lee * @date 2020-04-10 09:36:54 */ public class CompareBubbleAndInsertionSort { public static void main(String[] args) { //生成两个一样长度的随机数组 int length = 10000; int[] array_1 = generateArray(length); int[] array_2 = new int[length]; System.arraycopy(array_1, 0, array_2, 0, length); print(array_1); print(array_2); //比较冒泡排序与插入排序的耗时 long array_1_start = System.currentTimeMillis(); bubbleSort(array_1); System.out.println("bubbleSort cost time : " + (System.currentTimeMillis() - array_1_start)); long array_2_start = System.currentTimeMillis(); insertionSort(array_2); System.out.println("insertionSort cost time : " + (System.currentTimeMillis() - array_2_start)); //打印排序后的两个数组,看看结果是否正确 print(array_1); print(array_2); } /** * 生成随机数组 * @param length * @return */ private static int[] generateArray(int length) { Random r = new Random(); int[] array = new int[length]; for (int i = 0; i <array.length; i++) { array[i] = r.nextInt(length); } return array; } /** * 冒泡排序 * @param array */ private static void bubbleSort(int[] array) { for (int i = 0; i <array.length; i++) { //提前退出冒泡循环的标志 boolean hasSwitch = false; //因为使用 j 和 j+1 的下标进行比较,所以 j 的最大值为数组长度 - 2 for (int j = 0; j <array.length - (i+1); j++) { if (array[j] > array[j + 1]) { int temp = array[j + 1]; array[j+1] = array[j]; array[j] = temp; hasSwitch = true;//有数据交换 } } //没有数据交换退出循环 if (!hasSwitch) { break; } } } /** * 插入排序 */ private static void insertionSort(int[] array) { for (int i = 1; i <array.length; i++) { int j = i - 1; int value = array[i]; for (; j >= 0; j--) { if (array[j] > value) { array[j+1] = array[j]; } else { break; } } array[j+1] = value; } } /** * 打印数组 * @param array */ private static void print(int[] array) { for(int i : array) { System.out.print(i); } System.out.println(); } }
打印结果:
随着数组长度的提升,冒泡排序比插入排序多出的耗时也随之增多。