面试中可能被问到的常用排序算法,java面试题精选

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

复杂度

如果数据本身就是有序的,0次交换;最坏的情况下需要进行n-1次交换;比较操作次数固定为N2/2,时间复杂度为O(n2),空间复杂度为O(1)。

直接插入排序


插入排序是比较简单的排序方法,插入排序将待排序数组分为两部分,一部分是已排序部分,另一部分则是待排序部分。最开始仅第一个数字为已排序部分。然后每次从待排序部分取出一个数,同已排序部分的数据进行比较,选出刚好前一个数比该数小,后一个数比该数大(第一位除外),将该数放在这个位置。进过遍历后整个数组有序。

选择排序算法的运作如下:

  1. 将第一个数选择为已排序部分,取第二个数同第一个数比较,如果大于第一个数则不变,小于则交换位置。上述过程完成后将前两个数字作为已排序部分。

  2. 再次从待排序部分取出一个数字,重复上诉步骤找出该数的位置。从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。

  3. 重复上面的步骤直到将数据全部遍历完成则表示数组有序。

代码

public static void insertSort(int[] nums){

int i,j;

for (i=1;i<nums.length;i++){

int temp = nums[i];

//将元素后移

for (j=i-1;j>=0&&temp<nums[j];j–){

nums[j+1] = nums[j];

}

nums[j+1] = temp;

}

}

复杂度

在将n个元素的序列进行升序或者降序排列,采用插入排序最好情况就是序列已经是有序的了,在这种情况下,需要进行的比较操作需n-1次即可。最坏情况就是序列是反序的,那么此时需要进行的比较共有n(n-1)/2次。平均来说插入排序算法复杂度为 O(n^2)。所以插入排序不适合对于数据量比较大的排序应用。但是在需要排序的数据量很小或者若已知输入元素大致上按照顺序排列,插入排序的效率还是不错。

带哨兵的插入排序


在插入排序的时候,我们看到每一次进行比较都有两次比较操作j>=0&&temp<nums[j],即既要保证不越界又要判断数据是否符合条件,假设在反序的情况下就几乎多出一倍的比较次数。这里我们使用一个哨兵来消除掉多的比较操作。

代码

public static void insertWithSentinelSort(int[] nums){

int i,j;

for (i=1;i<nums.length;i++){

//将第一个元素指定为哨兵

//要求传入的数组比原数组长度大1

nums[0] = nums[i];

//将元素后移

//这里只需比较数据是否符合条件

for (j=i-1;nums[j]>nums[0];j–){

nums[j+1] = nums[j];

}

nums[j+1] = nums[0];

}

}

添加哨兵的好处就是将原本的比较次数减少,提高了算法效率。

希尔排序


希尔排序是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。

希尔排序是把记录按下标的一定的步长进行分组,对每组数据使用直接插入排序算法排序;随着步长逐渐减少,每组包含的关键词越来越多,当步长为1时,刚好就是一个插入排序。而在此时整个数据序列已经基本有序,插入排序在对几乎已经排好序的数据操作时,效率高,可以达到线性排序的效率。所以希尔排序的整体效率较高。

希尔排序的步骤:

  1. 选择步长大小,根据步长将数据分组

  2. 循环对每一组进行排序

  3. 修改步长的大小(一般为一半,也可以通过步长数组指定),重复1-2操作

  4. 直到步长为1进行排序后停止

代码

public static void shellSort(int[] nums){

int size = nums.length/2;

int i,j;

while(size>=1){

for (i=0;i<nums.length;i++){

for (j=i;j+size<nums.length;j+=size){

if(nums[j]>nums[j+size]){

swap(nums, j, j+size);

}

}

}

size/=2;

}

}

复杂度

希尔排序的时间复杂度分析比较复杂,因为它和所选取的步长有着直接的关系。步长的选取没有一个统一的定论,只需要使得步长最后为1即可。希尔排序的时间复杂度根据所选取的步长不同时间复杂度范围在o(n1.3)~o(n2)。

快速排序

快速排序是对冒泡排序的改进。

快排的基本步骤:

  1. 从待排序列中选取一个数(一般为第一个),进行一次排序,将大于该数的放在该数前面,小于该数的放在其后面。

  2. 上述操作将待排序列分为两个独立的部分,递归的进行上面的操作,直到序列无法再被分割。

  3. 最后一次排序后序列中是有序的。

代码

public static void quickSort(int[] nums, int low, int high){

if(low<high){

int partation = partition(nums, low, high);

//这里返回的low值的位置已经确定了 所以不用参与排序

quickSort(nums, 0, low-1);

quickSort(nums, low+1, high);

}

}

//进行一次排序 将待排序列分为两个部分

public static int partition(int[] nums, int low, int high){

//选取第一个值为枢纽值

int pivo = nums[low];

while(low<high){

while(low<high&&nums[high]>=pivo){

high–;

}

nums[low] = nums[high];

while(low<high&&nums[low]<=pivo){

low++;

}

nums[high]=nums[low];

}

nums[low] = pivo;

return low;

}

复杂度

时间复杂度

在最优情况下,Partition每次都划分得很均匀,如果排序n个关键字,其递归的深度就为log2n+1,即仅需递归log2n 次。时间复杂度为O(nlogn)。

最糟糕的情况就是待排序列为需要排序方向的逆序。每次划分只得到一个比上一次划分少一个记录的子序列。这时快排退化为冒泡排序。时间复杂度为O(n^2)。

快排的平均复杂度为O(nlogn),证明过程较长,直接贴个链接吧。

空间复杂度

被快速排序所使用的空间,根据上面我们实现的代码来看,在任何递归调用前,仅会使用固定的額外空間。然而,如果需要产生 o(logn)嵌套递归调用,它需要在他们每一个存储一个固定数量的信息。因为最好的情况最多需要O(logn)次的嵌套递归调用,所以它需要O(logn)的空间。最坏情况下需要 O(n)次嵌套递归调用,因此需要O(n)的空间。

归并排序


归并是指将两个及以上的有序序列合并成一个有序序列。

归并排序步骤:

  1. 申请一个和待排序列长度相同的空间空间该空间用来存放合并后的序列

  2. 设定两个数为对数组中位置的指向,最初位置分别为两个已经排序序列的起始位置

  3. 比较两个指针所指向的元素,选择小的元素放入到合并空间,并移动被选择的数的指针到下一位置

  4. 重复步骤3直到某一指针到达指定的序列尾部

  5. 将另一序列剩下的所有元素直接复制到合并序列尾

代码

public static void mergeSort(int[] nums, int[] temp, int left, int right){

if(left<right){

int mid = (left+right)/2;

mergeSort(nums, temp,left,mid);

mergeSort(nums, temp,mid+1,right);

最后

在面试前我整理归纳了一些面试学习资料,文中结合我的朋友同学面试美团滴滴这类大厂的资料及案例

MyBatis答案解析
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

大家看完有什么不懂的可以在下方留言讨论也可以关注。

觉得文章对你有帮助的话记得关注我点个赞支持一下!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
5079)]
由于篇幅限制,文档的详解资料太全面,细节内容太多,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!

大家看完有什么不懂的可以在下方留言讨论也可以关注。

觉得文章对你有帮助的话记得关注我点个赞支持一下!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-qbPQeXBL-1713557415079)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值