大厂面试-算法优化:冒泡排序你会优化吗?

news2025/1/19 11:02:15

关注公众号:”奇叔码技术“
回复:“java面试题大全”或者“java面试题”
即可领取资料

原文:冒泡排序及优化代码

https://blog.csdn.net/weixin_43989347/article/details/122025689

原文:十大经典排序算法


https://frxcat.fun/pages/eab19d/

内容分为:

1、总结算法思路

2、冒泡排序算法演示图

3、冒泡排序算法可运行代码

4、大厂面试会问到算法和算法优化

一、总结算法思路

冒泡排序是经典算法了,它的时间复杂度:最好O(n),最坏O(n^2)。

接下来直接说明它的优化算法思路:


自己理解:

第一次优化是指:如果内层循环经过一轮的比较,没有进入if判断语句进行交换,则代表后续的元素已经排好序了,已经是小的在前面,大的在后面,则也就证明了不用下一轮的比较了,直接退出循环,返回结果。


第二次优化是指:在原有第一次优化的基础上进行记录,经过内层循环的一轮比较,进入if判断语句,第j个数和第j+1个数比较,记录进行交换的交换位置的第j个数。内层循环一轮比较完毕之后,记录的第j个数,证明了,该数后面的数都已经排好序了,无序再进行排序。则下一轮的内层循环比较的最大索引位置就是第j个数,依此类推。


原作者的理解:

第一次优化:经过一轮的比较,如果没有交换,说明已经排好序了

第二次优化:记录每次最后一次交换的位置,说明这个位置往后,都是已经排好序了;那么下轮比较时,只需要比较到上次记录索引的位置即可。

二、冒泡排序算法演示图

冒泡排序

三、冒泡排序算法可运行代码

//冒泡排序,最好的O(n),最坏的O(n^2)
//第一次优化是指,如果内层循环经过一轮的比较,没有进入if判断语句进行交换,则代表后续的元素已经排好序了,已经是小的在前面,大的在后面,则也就证明了不用下一轮的比较了,直接退出循环,返回结果。
//第二次优化是指,再原有第一次优化的基础上进行记录,经过内层循环的一轮比较,进入if判断语句,第j个数和第j+1个数比较,,记录进行交换的交换位置的第j个数,
//内层循环一轮比较完毕之后,记录的第j个数,证明了,该数后面的数都已经排好序了,无序再进行排序。则下一轮的内存循环比较的最大索引位置就是第j个数,以此类推。
//原作者的理解:
//第一次优化:经过一轮的比较,如果没有交换,说明已经排好序了
//第二次优化:记录每次最后一次交换的位置,说明这个位置往后,都是已经排好序了;那么下轮比较时,只需要比较到上次记录索引的位置即可。


/*
 * n是数组个数,i代表循环次数,j代表每轮比较次数,count是算法一共比较的次数,
 * 冒泡排序:例子是从小大到排序
 *
 * 规律:
 *   从第一个数,依次往后进行比较,若第一个大于第二个数,则交换。(稳定排序)
 *   每一轮for循环,比较出一个最大或最小的数,放在确定的位置。

 *
 *
 * */
public class BulleSort {
    public static void main(String[] args) {
        bubble1();
        /*
        * bubble1();
        * 循环次数:
        *   n-1次    比如3个数,最多只需要循环2次,就可以得出结果
        * 每轮比较次数:
        *   n-1-i次  第一轮比较n-1,第二轮比较n-2,最后一轮比较n-1-(n-2)=1次
          这个算法,是固定循环n-1次,并且固定每轮比较次数:[n*(n-1)]/2
        * 缺点:
           当出现只需要交换一次的数组:{2,1,3,4,5},再用上面方法就资源浪费了
            排序前:
            2,1,3,4,5,
            排序后:
            1,2,3,4,5,
            总共比较次数:10  //优化后其实只需要比较7次就可以了
        */

       bubble2();
        /*
        * 优化:
        *   减少不必要的循环和比较次数。
        * 目标:
        *   数组{2,1,3,4,5},只需要循环2次,比较前两次循环的次数:(n-1)+(n-2)
        * 结果:
            排序前:
            2,1,3,4,5,
            排序后:
            1,2,3,4,5,
            总共比较次数:7

        */
        bubble3();
        /*
        * 经过上面的优化,可以将固定的比较次数,减少到循环2次,比较前两次循环次数
        * 那么有没有更好的优化方法呢?
           比如只要循环一次,就可以知道下次从没有确定最终位置的地方开始
        * 目标:
        *  1:数组{2,1,3,4,5},只需要循环1次,比较第1次循环的次数:(n-1)
        *  2:数组{1,2,3,5,4},只需要循环2次,比较前两次即可,是因为方法buble2()的test=1/0
        * 方法:
        *   记录每次最后一次交换的位置,说明这个位置往后,都是已经排好序了
        *   那么下轮比较时,只需要比较到上次记录索引的位置即可。
        *
        * */

    }

    public static void bubble3(){
        System.out.println("\n"+"方法三:每次循环,只需要比较未确定最终位置的数");
        int count=0;                        //总共比较次数
        int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};           //排序的数组
        int n = arr.length;                 //数组中有几个数

        int test = 0;
        /*如果某一次循环,没有交换,那就是已经排好序了。那么就退出。
        1假如可能排好序了,0代表肯定没有排好序 */
        int p1=0;   // 记录最后一次交换位置
        int p2=n-1;
        /*由于j循环,每次都需要判断j的本次i轮循环的最大比较位置
        所以需要引出p2,来通过本次确定已经排好序的位置,
        下次i轮循环时,j需要比较最大索引位置即可
        那么初始化,第一次比较次数应该是n-1次*/

        System.out.print("排序前:");
        print_Array(arr, n);                //打印数组

        //冒泡排序算法:
        for (int i = 0; i < n-1; i++) {        //一共循环n-1次
            test=1;                            //默认排好序了
            for (int j = 0; j < p2; j++) {  //比较n-1-i
                count++;                 //统计比较次数
                if(arr[j]>arr[j+1]) {          //第一个数和第二个数比较
                    test =0;                   //说明目前没有排好序
                    swap(arr,j,j+1);       //若第j个数大于第j+1个数,则交换
                    p1 = j;
                }
            }
            p2=p1;
            //下一轮比较的最大索引位置

            if(test==1) break;
            //经过一轮的比较,如果没有交换,说明已经排好序了
            p_Array(arr,n,i);                    //每轮循环的数组
        }
        System.out.print("排序后:");
        print_Array(arr, n);
        System.out.println("总共比较次数:"+count);
    }

    public static void bubble2(){
        System.out.println("\n"+"方法二:假如一次循环都没有交换,则说明已排好序");
        int test = 0;
        //如果某一次循环,没有交换,那就是已经排好序了。那么就退出。
        //1假如可能排好序了,0代表肯定没有排好序
        int count=0;                        //总共比较次数
        int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};           //排序的数组
        int n = arr.length;                 //数组中有几个数
        System.out.print("排序前:");
        print_Array(arr, n);                //打印数组

        //冒泡排序算法:
        for (int i = 0; i < n-1; i++) {        //一共循环n-1次
            test=1;                            //默认排好序了
            for (int j = 0; j < n-1-i; j++) {  //比较n-1-i
                count++;                 //统计比较次数
                if(arr[j]>arr[j+1]) {          //第一个数和第二个数比较
                    test =0;                   //说明目前没有排好序
                    swap(arr,j,j+1);       //若第j个数大于第j+1个数,则交换
                }
            }
            p_Array(arr,n,i);                    //每轮循环的数组
            if(test==1) break;
            //经过一轮的比较,如果没有交换,说明已经排好序了
        }

        System.out.print("排序后:");
        print_Array(arr, n);
        System.out.println("总共比较次数:"+count);
    }

    public static void bubble1(){
        System.out.println("方法一:未优化");
        int count=0;         //统计一共比较多少次数
        int[] arr = {3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};           //排序的数组
        int n = arr.length;  //数组中有几个数
        System.out.print("排序前:");
        print_Array(arr, n);          //打印数组

        //冒泡排序算法:
        for (int i = 0; i < n-1; i++) {        //一共循环n-1次
            for (int j = 0; j < n-1-i; j++) {  //比较n-1-i
                count++;                       //统计比较次数
                if(arr[j]>arr[j+1]) {          //第一个数和第二个数比较
                    swap(arr,j,j+1);       //若第j个数大于第j+1个数,则交换
                }
            }
            p_Array(arr,n,i);                    //每轮循环的数组
        }

        System.out.print("排序后:");
        print_Array(arr, n);          //打印数组
        System.out.println("总共比较次数:"+count);
    }


    //打印数组
    private static void print_Array(int[] arr, int length) {
        for (int i = 0; i < length; i++) {
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }
    //交换数组中两个数的位置
    public static void swap(int[] a,int a0,int a1){
        int temp = a[a0];
        a[a0] = a[a1];
        a[a1] = temp;
    }

    //打印每循环一轮的数组
    public static void p_Array(int[] arr,int length,int i1){
        System.out.print("第"+(i1+1)+"轮循环的数组:");
        for (int i = 0; i < length; i++) {
            System.out.print(arr[i] + ",");
        }
        System.out.println();
    }
}

四、大厂面试会问到算法和算法优化:

冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端。

作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位,所以最熟悉。


1.算法步骤

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。



2.算法优化

(1)记录进入if判断语句中比较之后的最后一次索引位置作为下一次内层循环的结束下标。

(2)记录没有进入if判断语句的flag标志,表明排序已完毕,无序再比较,退出循环,结束。


五、最后!!!

点赞
评论
关注我

END
下篇来临!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/414847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

矩阵相似题型总结

矩阵相似题型总结 &#xff08;一&#xff09;题型一&#xff1a;判断含重特征值的方阵A能否相似对角化&#xff08;即能否相似于对角阵&#xff09; 所有特征值均不同的矩阵必可相似对角化&#xff0c;含重特征值的矩阵呢&#xff1f;可如下做 &#xff08;1&#xff09;求A的…

C++linux高并发服务器项目实践 day4

Clinux高并发服务器项目实践 day4模拟实现ls -l指令文件属性操作函数access函数chmod 与chowntruncate函数目录操作函数mkdir和rmdirrenamechdir和getcwd目录遍历函数dup、dup2函数dupdup2fcntl函数模拟实现ls -l指令 #include<sys/types.h> #include<sys/stat.h>…

为何巴菲特和马斯克站在了一起?

股神巴菲特虽然非常传奇&#xff0c;但是马斯克对其并不感冒。马斯克曾经在一档电视节目中表示&#xff0c;实业才是王道&#xff0c;埋怨金融业抢走太多人才和精英&#xff0c;暗指巴菲特为年轻人做了错误示范。当然&#xff0c;巴菲特的投资非常厉害&#xff0c;但也有失手的…

2-修改example适用于不同开发板

1.问题 手上只有基于nRF52811芯片的BMD360开发板,与pca10056e开发板同一个芯片.所以pca10056e的example都可以适用于BMD360开发板,只需要修改开发板相同的输入输出硬件管脚即可.因为BMD360开发板与pca10056e开发板的输入输出管脚不同. 而BMD360开发板输入输出管脚于PCA10040相同…

【数据结构】七大排序算法详解Java

目录 1.排序算法分类 1.直接选择排序 代码展示&#xff1a; 2.直接插入排序 核心思路&#xff1a; 代码展示&#xff1a; ​编辑 3.希尔排序 思路分析&#xff1a; 代码展示&#xff1a; 4.归并排序 代码展示&#xff1a; 5.快速排序(挖坑法) 思路分析&#xff1a; …

OJ系统刷题 第十篇

13444 - 求出e的值 时间限制 : 1 秒 内存限制 : 128 MB 利用公式e11/!1​1/2!​1/3!​...1/n!​&#xff0c;求e的值&#xff0c;要求保留小数点后10位。 输入 输入只有一行&#xff0c;该行包含一个整数n&#xff08;2≤n≤15&#xff09;&#xff0c;表示计算e时累加到1/…

计算机操作系统第四版第六章输入输出系统—课后题答案

1.试说明I/O系统的基本功能。 隐藏物理设备的细节、与设备的无关性、提高处理机和I/O设备的利用率、对I/O设备进行控制、确保对设备的正确共享、错误处理 2.简要说明I/O软件的4个层次的基本功能。 用户层I/O软件&#xff1a;实现与用户交互的接口&#xff0c;用户可直接调用该层…

4.8、socket介绍

4.8、socket1. socket介绍1. socket介绍 所谓 socket&#xff08;套接字&#xff09;&#xff0c;就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端&#xff0c;提供了应用层进程利用网络协议交换数据的机制。从所处的地位…

阿里云centos7搭建ChatGPT网站

需要的环境 有一台外网的服务器 拥有一个OpenAI API Key Centos7&#xff08;其他服务器也行&#xff09; nodejs 前端github上 大神写的 https://github.com/ddiu8081/chatgpt-demo/ 一.安装node.js centos7 安装node.js 二.安装pnpm npm i -g pnpm三.下载web前端项目从…

【2023最新】超详细图文保姆级教程:App开发新手入门(3)

上文回顾&#xff0c;我们已经完成了一个应用项目创建、导入、代码更新、代码同步和代码提交&#xff0c;本章继续我们的新手开发之旅&#xff0c;讲述一下如何将开发完成的应用进行编译&#xff0c;生成可供他人安装、可上架的应用安装包。 6 应用打包 应用打包&#xff0c;…

27个必备的Python技巧,你一定要知道!

目录 01. 为什么使用缩进来分组语句&#xff1f; Guido van Rossum 认为使用缩进进行分组非常优雅&#xff0c;并且大大提高了普通 Python 程序的清晰度。大多数人在一段时间后就学会并喜欢上这个功能。 由于没有开始/结束括号&#xff0c;因此解析器感知的分组与人类读者之间…

免费英文在线翻译-英文自动翻译

免费的自动翻译器 作为一款免费的自动翻译器&#xff0c;我们的产品可以为全球用户提供高质量、高效率的翻译服务&#xff0c;帮助他们更好地沟通和交流。 现在&#xff0c;随着数字化的进一步发展&#xff0c;人们之间的跨文化交流越来越频繁。然而&#xff0c;语言偏差和文…

22-JavaScript

目录 1.什么是JavaScript&#xff1f; 1.1.JS、HTML、CSS关系 1.2.JS是如何运行的&#xff1f; 2.JS前置知识 2.1.第一个JS程序 PS&#xff1a;JS书写位置 2.2.JS书写格式 2.2.1.行内格式 ​2.2.2.内嵌格式 ​2.2.3.外部格式 2.3.注释&#xff08;script标签中&…

【软件测试】测试用例

目录 &#x1f337;1. 测试用例的基本要素 &#x1f337;2. 测试用例的设计方法 &#x1f333;2.1 基于需求进行测试用例的设计 ⭐️&#xff08;1&#xff09;功能需求测试分析 ⭐️&#xff08;2&#xff09;非功能需求测试分析 &#x1f333;2.2 具体的设计方法 &#…

【Python搞笑游戏】因蔡徐坤打篮球动作超火,被某程序员写成了一款游戏,画面美到不敢看,成功学到了精髓~(附源码免费)

导语 之前网络最火的梗&#xff0c;非“C徐坤打篮球”莫属。个人感觉&#xff0c;只有多年前的“春哥纯爷们”堪与匹敌&#xff01; 虽然说C徐坤打篮球是一个老梗了&#xff0c;但是确实非常搞笑&#xff0c;今天就跟着小编一起来回忆一下吧&#xff01; “我是练习两年半的…

qt - 隐式共享与d-pointer技术

文章目录前言1. 隐式共享2. d-pointer在隐式共享中的应用3. 二进制代码兼容4. d-pointer模式的实现5. QObject中的d-pointer前言 一般情况下&#xff0c;一个类的多个对象所占用的内存是相互独立的。如果其中某些对象数据成员的取值完全相同&#xff0c;我们可以令它们共享一块…

ESP32学习二-更新Python版本(Ubuntu)

一、简介 在一些场景里边&#xff0c;因为Python的版本过低&#xff0c;导致一些环境无法安装。这里来介绍以下&#xff0c;如何升级自己已安装的Python版本。例如如下情况&#xff1a; 二、实操 1.查看本地版本 python --version 2.添加源 sudo add-apt-repository ppa:jona…

FPGA时序知识点(基本方法总结就两点:1.降低时钟频率2.减小组合逻辑延迟(针对Setup Slack公式来的)

1.我们说的所有时序分析都是建立在同步电路的基础上的&#xff0c;异步电路不能做时序分析&#xff08;或者说只能做伪路径约束&#xff08;在设伪路径之前单bit就打拍&#xff0c;多bit就异步fifo拉到目的时钟域来&#xff09;&#xff09;。——FPGA 设计中寄存器全部使用一个…

逐一解释一下四个 “内存屏障” 是什么

什么是内存屏障&#xff1f;硬件层⾯&#xff0c;内存屏障分两种&#xff1a;读屏障&#xff08;Load Barrier&#xff09;和写屏障&#xff08;Store Barrier&#xff09;。内存屏障有两个作⽤&#xff1a; 阻⽌屏障两侧的指令重排序&#xff1b;强制把写缓冲区/⾼速缓存中的…

Matplotlib绘图

1.散点图 X1 [[3.393533211, 2.331273381], [3.110073483, 1.781539638], [1.343808831, 3.368360954], [3.582294042, 4.679179110], [2.280362439, 2.866990263], [7.423436942, 4.696522875], [5.745051997, 3.533989803], [9.172168622, 2.51…