JAVA 算法面试总结

news2024/11/22 5:43:54

1、二分查找

二分查找又叫折半查找,要求待查找的序列有序。每次取中间位置的值与待查关键字比较,如果中间位置
的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,
则在后半部分循环这个查找的过程。直到查找到了为止,否则序列中没有待查的关键字。
示例:

public static int biSearch(int []array,int a){

        int lo=0;
        int hi=array.length-1;
        int mid;
        while(lo<=hi){

            mid=(lo+hi)/2;//中间位置
            if(array[mid]==a){

                return mid+1;

            }else if(array[mid]<a){ //向右查找

                lo=mid+1;

            }else{ //向左查找


                hi=mid-1;
            }
        }
        return -1;
    }

2、冒泡排序算法

(1)比较前后相邻的二个数据,如果前面数据大于后面的数据,就将这二个数据交换。
(2)这样对数组的第 0 个数据到 N-1 个数据进行一次遍历后,最大的一个数据就“沉”到数组第
N-1 个位置。

(3)N=N-1,如果 N 不为 0 就重复前面二步,否则排序完成。

public static void bubbleSort1(int[] a, int n) {
        int i, j;
        for (i = 0; i < n; i++) {//表示 n 次排序过程
            for (j = 1; j < n - i; j++) {
                if (a[j - 1] > a[j]) {//前面的数字大于后面的数字就交换
                    //交换 a[j-1]和 a[j]
                    int temp;
                    temp = a[j - 1];
                    a[j - 1] = a[j];
                    a[j] = temp;
                }
            }
        }
    }

3、插入排序算法

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。
插入排序非常类似于整扑克牌。在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从
桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将
它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。
如果输入数组已经是排好序的话,插入排序出现最佳情况,其运行时间是输入规模的一个线性函
数。如果输入数组是逆序排列的,将出现最坏情况。平均情况与最坏情况一样,其时间代价是(n2)。
在这里插入图片描述

public void sort(int arr[])
    {
       for (int i = 1; i < arr.length; i++) {
            //插入的数
            int insertVal = arr[i];
            //被插入的位置(准备和前一个数比较)
            int index = i - 1;

            //如果插入的数比被插入的数小
            while (index >= 0 && insertVal < arr[index]) {
                //将把 arr[index] 向后移动
                arr[index + 1] = arr[index];
                //让 index 向前移动
                index--;
            }
            //把插入的数放入合适位置
            arr[index + 1] = insertVal;
        }
    }

4、快速排序算法

快速排序的原理:选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),
比基准值大的都在右边(一般是无序的)。一般选择序列的第一个元素。
一次循环:从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果没有
继续比较下一个,直到找到第一个比基准值小的值才交换。找到这个值之后,又从前往后开始比
较,如果有比基准值大的,交换位置,如果没有继续比较下一个,直到找到第一个比基准值大的
值才交换。直到从前往后的比较索引>从后往前比较的索引,结束第一次循环,此时,对于基准值
来说,左右两边就是有序的了

public void sort(int[] a, int low, int high) {
        int start = low;
        int end = high;
        int key = a[low];

        while (end > start) {

            //从后往前比较
            while (end > start && a[end] >= key)
                //如果没有比关键值小的,比较下一个,直到有比关键值小的交换位置,然后又从前往后比较
                end--;
            if (a[end] <= key) {

                int temp = a[end];
                a[end] = a[start];
                a[start] = temp;
            }
            //从前往后比较
            while (end > start && a[start] <= key)
                //如果没有比关键值大的,比较下一个,直到有比关键值大的交换位置
                start++;
            if (a[start] >= key) {
                int temp = a[start];
                a[start] = a[end];
                a[end] = temp;
            }

        //此时第一次循环比较结束,关键值的位置已经确定了。左边的值都比关键值小,右边的值都比关键值大,但是两边的顺序还有可能是不一样的,进行下面的递归调用
        }
        //递归
        if (start > low) sort(a, low, start - 1);//左边序列。第一个索引位置到关键值索引-1
        if (end < high) sort(a, end + 1, high);//右边序列。从关键值索引+1 到最后一个
    }

在这里插入图片描述

5、希尔排序算法

基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列
中的记录“基本有序”时,再对全体记录进行依次直接插入排序。

  1. 操作方法:
    选择一个增量序列 t1,t2,…,tk,其中 ti>tj,tk=1;
  2. 按增量序列个数 k,对序列进行 k 趟排序;
  3. 每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进
    行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长
    度。
    在这里插入图片描述
private void shellSort(int[] a) {
        int dk = a.length / 2;
        while (dk >= 1) {
            ShellInsertSort(a, dk);
            dk = dk / 2;
        }
    }

    private void ShellInsertSort(int[] a, int dk) {
//类似插入排序,只是插入排序增量是 1,这里增量是 dk,把 1 换成 dk 就可以了
        for (int i = dk; i < a.length; i++) {
            if (a[i] < a[i - dk]) {
                int j;
                int x = a[i];//x 为待插入元素
                a[i] = a[i - dk];
                for (j = i - dk; j >= 0 && x < a[j]; j = j - dk) {
//通过循环,逐个后移一位找到要插入的位置。
                    a[j + dk] = a[j];
                }
                a[j + dk] = x;//插入
            }
        }
    }

6、归并排序算法

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列
分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
在这里插入图片描述

public static void main(String[] args) {
        int[] data = new int[]{5, 3, 6, 2, 1, 9, 4, 8, 7};
        print(data);
        mergeSort(data);
        System.out.println("排序后的数组:");
        print(data);

    }

    public static void mergeSort(int[] data) {
        sort(data, 0, data.length - 1);

    }

    public static void sort(int[] data, int left, int right) {
        if (left >= right)
            return;
        // 找出中间索引
        int center = (left + right) / 2;
        // 对左边数组进行递归
        sort(data, left, center);
        // 对右边数组进行递归
        sort(data, center + 1, right);
        // 合并
        merge(data, left, center, right);
        print(data);
    }

    /**
     * 将两个数组进行归并,归并前面 2 个数组已有序,归并后依然有序
     * Page 239 of 283
     *
     * @param data   数组对象
     * @param left   左数组的第一个元素的索引
     * @param center 左数组的最后一个元素的索引,center+1 是右数组第一个元素的索引
     * @param right  右数组最后一个元素的索引
     */
    public static void merge(int[] data, int left, int center, int right) {
        // 临时数组
        int[] tmpArr = new int[data.length];
        // 右数组第一个元素索引
        int mid = center + 1;
        // third 记录临时数组的索引
        int third = left;
        // 缓存左数组第一个元素的索引
        int tmp = left;
        while (left <= center && mid <= right) {
        // 从两个数组中取出最小的放入临时数组
            if (data[left] <= data[mid]) {
                tmpArr[third++] = data[left++];
            } else {
                tmpArr[third++] = data[mid++];
            }
        }
        // 剩余部分依次放入临时数组(实际上两个 while 只会执行其中一个)
        while (mid <= right) {
            tmpArr[third++] = data[mid++];
        }
        while (left <= center) {
            tmpArr[third++] = data[left++];
        }
        // 将临时数组中的内容拷贝回原数组中
        // (原 left-right 范围的内容被复制回原数组)
        while (tmp <= right) {

            data[tmp] = tmpArr[tmp++];
        }

    }

    public static void print(int[] data) {
        for (int i = 0; i < data.length; i++) {
            System.out.print(data[i] + "\t");
        }
        System.out.println();
    }

7、桶排序算法

桶排序的基本思想是: 把数组 arr 划分为 n 个大小相同子区间(桶),每个子区间各自排序,最
后合并 。计数排序是桶排序的一种特殊情况,可以把计数排序当成每个桶里只有一个元素的情况。
1.找出待排序数组中的最大值 max、最小值 min
2.我们使用 动态数组 ArrayList 作为桶,桶里放的元素也用 ArrayList 存储。桶的数量为(maxmin)/arr.length+1
3.遍历数组 arr,计算每个元素 arr[i] 放的桶
4.每个桶各自排序

public static void bucketSort(int[] arr) {
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(max, arr[i]);
            min = Math.min(min, arr[i]);
        }
        //创建桶
        int bucketNum = (max - min) / arr.length + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
        for (int i = 0; i < bucketNum; i++) {
            bucketArr.add(new ArrayList<Integer>());
        }
        //将每个元素放入桶
        for (int i = 0; i < arr.length; i++) {
            int num = (arr[i] - min) / (arr.length);
            bucketArr.get(num).add(arr[i]);
        }
        for (int i = 0; i < bucketArr.size(); i++) {
            Collections.sort(bucketArr.get(i));
        }
    }

8、基数排序算法

将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位
开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。

public class radixSort {
        int a[] = {49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 5, 4, 62, 99, 98, 54, 101, 56, 17, 18, 23, 34, 15, 35, 25, 53, 51};

        public radixSort() {
            sort(a);
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
        }

        public void sort(int[] array) {
            //首先确定排序的趟数;
            int max = array[0];
            for (int i = 1; i < array.length; i++) {
                if (array[i] > max) {
                    max = array[i];
                }
            }
            int time = 0;
            //判断位数;
            while (max > 0) {
                max /= 10;
                time++;
            }
            //建立 10 个队列;
            List<ArrayList> queue = new ArrayList<ArrayList>();
            for (int i = 0; i < 10; i++) {
                ArrayList<Integer> queue1 = new ArrayList<Integer>();
                queue.add(queue1);
            }
            //进行 time 次分配和收集;
            for (int i = 0; i < time; i++) {
                //分配数组元素;
                for (int j = 0; j < array.length; j++) {
                    //得到数字的第 time+1 位数;
                    int x = array[j] % (int) Math.pow(10, i + 1) / (int) Math.pow(10, i);
                    ArrayList<Integer> queue2 = queue.get(x);
                    queue2.add(array[j]);
                    queue.set(x, queue2);
                }
                int count = 0;//元素计数器;
                //收集队列元素;
                for (int k = 0; k < 10; k++) {
                    while (queue.get(k).size() > 0) {
                        ArrayList<Integer> queue3 = queue.get(k);
                        array[count] = queue3.get(0);
                        queue3.remove(0);
                        count++;
                    }
                }
            }
        }
    }

9、剪枝算法

在搜索算法中优化中,剪枝,就是通过某种判断,避免一些不必要的遍历过程,形象的说,就是
剪去了搜索树中的某些“枝条”,故称剪枝。应用剪枝优化的核心问题是设计剪枝判断方法,即
确定哪些枝条应当舍弃,哪些枝条应当保留的方法
在这里插入图片描述

10、回溯算法

回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现
已不满足求解条件时,就“回溯”返回,尝试别的路径。

11、最短路径算法

从某顶点出发,沿图的边到达另一顶点所经过的路径中,各边上权值之和最小的一条路径叫做最
短路径。解决最短路的问题有以下算法,Dijkstra 算法,Bellman-Ford 算法,Floyd 算法和 SPFA
算法等。

12、最小生成树算法

现在假设有一个很实际的问题:我们要在 n 个城市中建立一个通信网络,则连通这 n 个城市需要
布置 n-1 一条通信线路,这个时候我们需要考虑如何在成本最低的情况下建立这个通信网?
于是我们就可以引入连通图来解决我们遇到的问题,n 个城市就是图上的 n 个顶点,然后,边表示
两个城市的通信线路,每条边上的权重就是我们搭建这条线路所需要的成本,所以现在我们有 n 个
顶点的连通网可以建立不同的生成树,每一颗生成树都可以作为一个通信网,当我们构造这个连
通网所花的成本最小时,搭建该连通网的生成树,就称为最小生成树。

构造最小生成树有很多算法,但是他们都是利用了最小生成树的同一种性质:MST 性质(假设
N=(V,{E})是一个连通网,U 是顶点集 V 的一个非空子集,如果(u,v)是一条具有最小权值的边,
其中 u 属于 U,v 属于 V-U,则必定存在一颗包含边(u,v)的最小生成树),下面就介绍两种使
用 MST 性质生成最小生成树的算法:普里姆算法和克鲁斯卡尔算法。
在这里插入图片描述

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

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

相关文章

MySQL(主从复制)

简述&#xff1a;主从复制&#xff0c;是用来建立一个和主数据库完全一样的数据库环境&#xff0c;称为从数据库&#xff0c;主数据库一般是准实时的 业务数据库、事务处理库&#xff0c;从库做查询库。 复制过程简单的说就是 master 将数据库的改变写入二进制日志&#xff0c…

JOSEF电流继电器 DL-33 整定范围0.5-2A 柜内安装板前接线

系列型号&#xff1a; DL-31电流继电器; DL-32电流继电器; DL-33电流继电器; DL-34电流继电器; 一、用途 DL-30系列电流继电器用于电机保护、变压器保护和输电线的过负荷和短路保护线路中&#xff0c;作为起动元件。 二、结构和原理 继电器系电磁式&#xff0c;瞬时动作…

电脑缺失vcruntime140_1.dll有什么办法解决,修复vcruntime140_1.dll丢失

电脑缺失vcruntime140_1.dll有什么办法解决&#xff0c;vcruntime140_1.dll文件的作用又是什么&#xff0c;这个文件有什么作用&#xff1f;是一个什么样的文件&#xff1f;如果要修复vcruntime140_1.dll文件都有什么办法能够解决呢&#xff1f;今天这篇文章就和大家聊一聊关于…

ProFTPD-1.3.3c Backdoor Command Execution漏洞复现+poc

https://www.whereisk0shl.top/post/proftpd-1.3.3chou-men-fen-xi https://github.com/proftpd/proftpd 在官网和官方github上找了一圈1.3.3c版本的proftpd&#xff0c;应该是漏洞太多&#xff0c;官方把下了 https://blog.csdn.net/morrino/article/details/115836400 这个文…

MySQL--InnoDB引擎

InnoDB引擎 逻辑存储引擎 表空间→段→区→页→行 Tablespace 表空间&#xff08;ibd文件&#xff09;&#xff1a;一个mysql实例可以对应多个表空间&#xff0c;用于存储记录、索引等数据Segment 段&#xff1a;段分为数据段、索引段、回滚段&#xff0c;InnoDB是索引组织表…

山西电力市场日前价格预测【2023-11-28】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-28&#xff09;山西电力市场全天平均日前电价为283.92元/MWh。其中&#xff0c;最高日前电价为437.70元/MWh&#xff0c;预计出现在17:45。最低日前电价为0.00元/MWh&#xff0c;预计出…

2023年最新Dev-C++下载安装以及C语言环境搭建教程(C语言入门)

文章目录 写在前面C语言简介Dev-C简介Dev-C下载安装Dev-C使用教程 写在后面 写在前面 2023年最新Dev-C下载安装以及C语言环境搭建教程&#xff0c;快来看看吧&#xff01; C语言简介 C语言是一种通用的高级程序设计语言&#xff0c;由美国计算机科学家Dennis Ritchie于20世纪…

Java抽象类和接口(2)

&#x1f435;本篇文章继续对接口相关知识进行讲解 一、排序 1.1 给一个对象数组排序&#xff1a; class Student {public String name;public int age;public Student(String name, int age) {this.name name;this.age age;}public String toString() {return "name:…

【Axure高保真原型】3D金字塔图_移入显示数据标签

今天和大家分享3D金字塔图_移入显示数据标签的原型模板&#xff0c;鼠标金字塔区域时&#xff0c;对应区域会变绿&#xff0c;可以查看该区域对应的项目和数据&#xff0c;这个原型模板是用Axure原生元件制作的&#xff0c;所以无需联网&#xff0c;而且可以自由修改样式、交互…

Allegro层叠中的介电常数如何填写指导说明

Allegro层叠中的介电常数如何填写指导说明 在用Allegro进行PCB设计的时候,需要在cross-section中设置好每个层的信息,包括层命名,每层的厚度等等信息。如下图 一般来说,这些信息就足够了 但是对于有仿真需求或者等长设计需要使用ps作为延时单位的设计的时候,需要额外在层…

postman自动化接口测试

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

Java基础小结

Java 基础小结 Java 基础概念与常识 什么是 Java ? Java 是 1995 年由 sun 公司推出的一门高级语言。 Java 的四个基本特性是面向对象、平台无关性、安全性和简单性。 具体特点如下: 简单易学。 平台无关性。 面向对象 面向对象是一种程序设计技术&#xff0c;以木匠工…

Docker配置Halo搭建个人博客-快速入门

Docker配置Halo搭建个人博客-快速入门 1 官方文档2 安装Halo2.1 创建Halo主目录2.2 远程下载配置文件2.3 编辑配置文件2.4 拉取最新镜像2.6 查看容器2.7 开放服务器的防火墙 3 运行3.1 运行项目3.2 停止项目 4 常见问题4.1 没有权限4.2 ommand netstart not found, did you mea…

体育网站的技术 SEO:完整指南

您熟悉体育网站管理行业的快节奏、不断变化的性质。您的网站提供最新的体育新闻和信息&#xff0c;包括实时比分更新。但是&#xff0c;如果人们不容易找到它&#xff0c;那么你所有的精彩内容都是徒劳的。这就是体育网站技术 SEO 综合指南的用武之地&#xff01; 本指南将教您…

【axios】拦截器:axios.interceptors.request.use|axios.interceptors.response.use

文章目录 概述设置拦截器Axios 拦截器的实现任务注册任务编排任务调度 来源 概述 axios有请求拦截器&#xff08;request&#xff09;、响应拦截器&#xff08;response&#xff09;、axios自定义回调处理&#xff08;这里就是我们常用的地方&#xff0c;会将成功和失败的回调…

论文阅读——DINOv

首先是关于给了提示然后做分割的一些方法的总结&#xff1a; 左边一列是prompt类型&#xff0c;右边一列是使用各个类型的prompt的模型。这些模型有分为两大类&#xff1a;Generic和Refer&#xff0c;通用分割和参考分割。Generic seg 是分割和提示语义概念一样的所有的物体&am…

开源四轴协作机械臂ultraArm激光雕刻技术案例!

注意安全事项 开始之前&#xff0c;请确保您已采取适当的安全措施&#xff0c;例如用于激光操作的防护眼镜、灭火器和通风良好的区域。 引言 随着科技的不断进步&#xff0c;激光雕刻技术已经成为当今制造行业中不可或缺的一部分。它以其高精度、高效率和广泛的材料适应性&…

Docker可视化工具Portainer(轻量)或者Docker容器监控之 CAdvisor+InfluxDB+Granfana(重量)

Docker轻量级可视化工具Portainer 是什么 Portainer 是一款轻量级的应用&#xff0c;它提供了图形化界面&#xff0c;用于方便地管理Docker环境&#xff0c;包括单机环境和集群环境。 安装 官网 https://www.portainer.io/ https://docs.portainer.io/v/ce-2.9/start/instal…

springboot+vue实现websocket通信实例,进入页面建立连接

springbootvue实现websocket通信实例 进入页面建立连接 前端代码&#xff1a; <template><div class"app-container"><el-form :model"queryParams" ref"queryForm" size"small" :inline"true" v-show&qu…

uniapp基础-教程之HBuilderX基础常识篇03

该内容为了大家更好的理解&#xff0c;将每个页面进行分离&#xff0c;单独创建项目&#xff0c;如在index中之写只写了一个搜索框&#xff0c;将其他页面分别放在HBuilderX目录中的components中&#xff0c;没有的可自行创建。 然后在components中创建轮播图新建一个swiper.v…