冒泡排序的优化你真的不知道?面试踩坑优化

Posted 大数据修行直通车

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序的优化你真的不知道?面试踩坑优化相关的知识,希望对你有一定的参考价值。

点击上方“大数据修行直通车”,选择星标
进入公众号点击“学习资源”,加入大数据群,获取各类技术资料
冒泡排序的优化你真的不知道?【面试踩坑优化】

排序算法之冒泡排序

一定看到最后,算法最重要的就是不断优化,思路最重要

最基本概念:重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

【课代表总结】最简单的冒泡也有很多门道!!!面试过程中,多和面试官沟通自己的思路,不断优化,探讨,比干巴巴的写写写更容易offer到手

1、基本思路(从小到大排序)

  • 通过对待排序序列从前往后依次比较,若发现逆序(前一个数字大于后一个数字)则交换位置,使值较大的元素逐渐从前移动到后部。

  • 设待排序列为arr[5]={10,1,3,2,9},设置一个临时变量temp,用来帮助两个值的交换。第一趟排序首先比较arr[0]和arr[1],发现arr[0]>arr[1],则两个数值交换位置 然后再比较arr[1]和arr[2],依次类推。

(1)第一趟排序代码为:

int first=0,last=0,temp=0;
for(int i=0;i<arr.length-1;i++){
if(arr[i]>arr[i+1]){
temp=arr[first];
arr[first]=arr[last];
arr[last]=temp;
}
}
  • 第一趟排序之后的结果是:arr[5]={1,3,2,9,10};即将数组中最大的数移动到数组的尾部。在第二趟排序中只需要比较前四个数值就可以了,即前arr.length-1个数值。

(2)在第二趟排序中找到第二大的数值,并放在数组中倒数第二个位置,因此第三趟排序只需要比较前arr.length-2个数就可以了。依次类推,当完成arr.length-1次排序之后,就可以保证整个数组是有序的。代码表示如下:

public static void bobbsort(int[] arr){
int temp=0;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
System.out.println(Arrays.toString(arr));
}

2、优化

  • 通过上一个例子arr[5]={10,1,3,2,9}可以看出,在第一趟排序后得到的结果为 arr[5]={1,3,2,9,10};第二趟的排序结果为arr[5]={1,2,3,9,10},此时数组已经有序,后面的第三趟第四趟排序完全是浪费时间。

  • 因此我们可以通过设置一个flag来判断每趟排序是否有交换;若没有交换,则说明数组已经有序,可以退出循环。具体代码为:

public static void bobbsort(int[] arr){
int temp=0;
boolean flag=false;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
flag=true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
if(!flag){ //如果flag的值依旧为false 则说明没有交换
break;
}else{ //否则flag的值为true,说明交换 此时 要将flag的值重新置为false
//进行下一次的判断
flag=false;
}
}
System.out.println(Arrays.toString(arr));
}

3、二次优化

  • 在冒泡排序的过程中,经常会遇到这样的一种情况:在第i趟排序过程中,第i大的数据已经在相应的位置了,甚至第i-1大的数据也已经在相应的位置上了,这样我们在进行第i趟排序时会出现多余的比较。

  • 比如数组arr[5]={10,4,3,8,9},第一趟排序后结果为arr[5]={4,3,8,9,10},此时,元素8,9已经在相应的位置上了,但是在第二趟排序中依旧会做比较。

  • 因此,为了避免多余的比较,设置一个变量标记每趟排序后最后的交换位置,在进行下一趟排序时,只要比较最后交换位置之前的元素即可。代码如下:

public static void bobbsort(int[] arr){
int temp=0;
boolean flag=false;
int lacat=0; //标记最后交换的位置
int len=arr.length-1;
for(int i=0;i<arr.length-1;i++){
for(int j=0;j<len;j++){
if(arr[j]>arr[j+1]){
flag=true;
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
lacat=j;
}
}
len=lacat;
if(!flag){ //如果flag的值依旧为false 则说明没有交换
break;
}else{ //否则flag的值为true,说明交换 此时 要将flag的值重新置为false
//进行下一次的判断
flag=false;
}
}
System.out.println(Arrays.toString(arr));
}

4、优化前后性能比较

  • 冒泡排序算法在优化前最好和最坏情况下时间复杂度都为O(n^2), 而在第一次优化和第二次优化之后最坏的情况下依旧为O(n^2),但是最好的情况下时间复杂度变为O(n)。

  • 相比较第一次优化和第二次优化在程序中设置80000个随机整数数组,分别记录时间,代码如下:

public static void main(String[] args) {
int[] arr=new int[80000];
for(int i=0;i<80000;i++) {
arr[i]=(int)(Math.random()*800000);
}

System.out.println("排序前时间为");
Date date1=new Date();
SimpleDateFormat simpaleDateFormat=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str=simpaleDateFormat.format(date1);
System.out.println(date1Str);

bobbsort2(arr);

Date date2=new Date();
String date2Str=simpaleDateFormat.format(date2);
System.out.println("排序完成的时间为:"+date2Str);

}

5、实战对比执行时间

(1)未优化时运行时间 
冒泡排序的优化你真的不知道?【面试踩坑优化】
(2)第一次优化后运行时间 
冒泡排序的优化你真的不知道?【面试踩坑优化】

(3)两次优化后运行时间 

冒泡排序的优化你真的不知道?【面试踩坑优化】

6、总结

  • 上面算法的优化思路,绝对可以让你与众不同。

  • 无论简单的算法还是更为复杂的,主要是解决问题的思路,举一反三,多思考,很多地方都可以应用的到!


PS: 笔者刚建了个学习交流群,禁广告、推广,大家有啥问题也可以在群里提问,有需要的小伙伴可以加一下~

加群方式 - 扫描下方

以上是关于冒泡排序的优化你真的不知道?面试踩坑优化的主要内容,如果未能解决你的问题,请参考以下文章

面试之选择排序——你会怎么优化她面试踩坑优化

面试必考算法题之冒泡排序 (优化脱坑版)!

我知道你会冒泡排序,但是你会优化冒泡排序吗?

面试 | 冒泡排序优化

你真的会写冒泡排序吗?

动画:如何给面试官写一个满意的冒泡排序