首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java开发 2019秋招 面经整理

Java类加载器 类加载器加载一个类过程有哪些 新建一个对象怎么分配内存 HashMap为什么在数据较多时用红黑树而不是链表 快排和堆排序,什么情况下用快排,数组比较有序情况下用什么排序 程序运行慢...,怎么排查 红黑树特点 数组和链表区别,删除数组最后一位和删除链表最后一位哪个更快,为什么?...接口和类区别 构造方法和一般方法区别 手写代码 两个链表求交叉节点 给定长度为n数组,给定k,求出其中出现次数大于n/k 手写两个线程,一个发送消息,一个接收消息 给定字符串,找出第一个只出现一次字符...手写单例模式 传入一个数组,把数组元素转为单链表 反转单链表 传入一个数组,如果一个元素为0,则对应行和列都置位0 最大连续子数组和 找出出现次数大于数组长度一半数字 m行n列,从左上角到右下角有多少种走法...写sql 语句,找出平均分大于80分课程。

89510

堆和堆排序

尽管这两种排序算法时间复杂度都是 image.png ,甚至堆排序比快速排序时间复杂度还要稳定,但是,在实际软件开发中,快速排序性能要比堆排序好,这是为什么呢?...罗列了两点要求,只要满足这两点,它就是一个堆。 堆是一个完全二叉树; 堆中每一个节点值都必须大于等于(或小于等于)其子树中每个节点值。 分别解释一下这两点。 第一点,堆必须是一个完全二叉树。...当我们删除堆顶元素之后,就需要把第二大元素放到堆顶,那第二大元素肯定会出现在左右子节点中。然后我们再迭代地删除第二大节点,以此类推,直到叶子节点被删除。 这里也画了一个分解图。...第一种建堆思路处理过程是从前往后处理数组数据,并且每个数据插入堆中,都是从下往上堆化。而第二种实现思路,是从后往前处理数组,并且每个数据都是从上往下堆化。...代码 https://gitee.com/kaiLee/struct/tree/master/src/main/java/com/s11/heap 参考 28 | 堆和堆排序为什么堆排序没有快速排序快

27110
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    堆排序(向下调整法,向上调整法详解)

    一、 二叉树顺序结构 普通二叉树是不适合用数组来存储,因为可能会存在大量空间浪费。而完全二叉树更适合使用顺序结构存储。...三、数组存储、顺序存储规律 如果要用数组存储二叉树,那么必须要符合顺序存储中父子存储规律 此处可能会有疑问,左右孩子父节点计算为什么可以归纳为一个结论了?...child表示当前要进行向上调整节点索引。在堆排序中,当我们向堆中插入一个新元素,这个新元素通常被放置在数组末尾,然后可能需要通过向上调整来确保它满足堆性质。...parent表示当前要调整节点索引。在堆排序中,当我们从堆中移除堆顶元素并与堆最后一个元素交换,我们需要对新堆顶元素进行向下调整以确保堆性质得到维护。...有一个数列,请用堆排序升序排列 如果使用向下调整法建小堆,先把0视为堆根,0和3交换,然后当3视为堆根: 所以要建大堆: 堆排序时间复杂度与向上调整法建堆时差不多 子节点大于父节点交换,建大堆,

    31510

    堆和堆排序

    首先堆前提条件是一个完全二叉树,所以我们可以采用数组进行实现,如下图所示堆,我们可以变成数组为{10,7,6,3,4,5,2},但是我们怎么来知道他们之间关系呢?比如7和6父是10,怎么知道呢?...,所以可能不满足堆,我们可以找到他子节点中最大值,和他进行交换,交换完毕以后再找子节点中最大进行交换,直到到了叶子结点,也就是i*2+1大于数组长度结束,如下图所示,我们删除7这个数据。...其中用橙色标记就是下标,我们现在2开始,下一次就是1,再下一次就是0,所以为什么要做递减,而2就是5/2-1。...写了一份Java代码实现如下所示。 Java实现堆排序 ?...4.时间复杂度和空间复杂度 首先堆排序是一个不稳定排序算法,因为再交换后会继续堆化,所以会改变相同值前后顺序,堆排序是一个原地排序算法,因为只是使用了一些临时变量,空间复杂度为O(1);建堆过程时间复杂度是

    48941

    【初阶数据结构】理解堆特性与应用:深入探索完全二叉树独特魅力

    初阶数据结构笔记专栏: 初阶数据结构笔记 喜欢诗句:无人扶青云志 自踏雪至山巅 一、二叉树顺序结构 普通二叉树是不适合用数组来存储,因为可能会存在大量空间浪费。...以下代码部分是根据建小堆来走,如果需要建大堆可以修改直接大于小于号。 堆总是一颗完全二叉树,对于搭建完全二叉树结构,一般采用数组作为存储结构,而完全二叉树作为逻辑结构。...堆向下调整算法只用于根节点不满某种条件使用向下调正算法进行调整,至于使用向下调整算法不能达到我们预期,比如现在建小堆,从根节点和根左右节点调整,由于左右子树不是一个小堆,无法保证此时根就是最小值...3.5.1 挪移数据覆盖删除 挪移数据覆盖会导致堆发生严重BUG,整棵树父子关系全乱,也就是需要维持大小关系乱了(拿你当兄弟,你却像当我爹) 3.5.2 首尾交换再删除 对于堆删除,我们采用另外一种方法...上面对于堆调整不是叫做堆排序堆排序是对数组元素进行操作 堆排序即是运用堆思想进行排序,总共分为两个步骤:建堆和利用堆删除思想进行排序 1.建堆 (后面有解释) 升序:建大堆 降序:建小堆

    12710

    【排序篇】插入排序与选择排序

    ,是tmp大于arr[end]所以tmp要在end后面 //可不能写成arr[end] = tmp,这样写程序会崩溃 } } int main() { int arr[10] = { 0,9,8,7,6,5,4,3,2,1...当gap>1都是预排序,目的是为了让数组更接近有序。...当gap = 1数组已经接近有序了,这样直接插入排序就会很快。整体而言,可以达到优化效果。...以下图为例:以10为根左右子树,都满足小堆(堆)性质,只有根节点不满足,因此只需将根节点往下调,整合到合适位置就可以了。...回答:堆排序本质是选择排序,每次都要选择一个最大数到数组最后一位,那么问题就变成了如何选择最大数到数组最后一位,要找出堆中最大数就必须要用到大堆,因为大堆中最大数就在堆堆顶,通过一次次选择就可以将数组排序

    9110

    三刷”数组第K个最大元素“,终于学会了堆排序

    () 方法也用不亦乐乎,但是提起堆排序肯定是马马虎虎,因为也是,leetcode有这么一道题,刷了3遍,终于弄明白了堆排序,今天和大家分享一下,如果能帮到你,那真是太好了!...但是直到,参加高德地图面试, 上来就是问原题,返回数组中第K个最大元素,使用堆排序。...语塞,半天没说话,这不按套路出牌啊 面试官,继续发问,有听说堆排序说听说,但没有写过 面试官:好吧,那就不问了 ......结果当然是凉凉了 于是痛定思痛,决心一定要搞清楚堆排序 第三次刷...看到了leetcode题解,大大得写着一句话 所以今天带着大家一起用堆排序重刷一遍 前置知识 堆 heap 完全二叉树 父节点内容大于子节点内容 堆必须满足 以上两个条件,必须是完全二叉树,且父节点大于子节点...父节点内容大于子节点内容 故名思义,每个父节点内容,都大于子节点值,就不展开解释了 怎样用代码表示一个堆 用数组可以表示一个堆 因为堆是从上至下,从左至右构建,我们可以给每个节点加上标识 正好可以用一个数组来存储这些标识

    41730

    面试中排序算法(Part 3)

    大根堆和小根堆 堆树定义如下: 堆树是一颗完全二叉树 堆树的当前节点总是不大于或者不小于其孩子节点值,如果不大于其孩子节点,叫做小根堆。...大根堆和小根堆 那么我们知道了堆特性之后,我们就可以使用结构对一个列表进行排序,通常为了编程和实现简单,我们会使用数组来模拟堆结构,假设原始数组为a={4,1,3,2,16,9,10,14,8,7...大根堆结构 建立堆以及调整堆 那么我们如何使用数组来表述堆这种结构呢?...i+1,如果超过索引,则没有左节点 右节点索引为:2*i+2,如果超过索引,则没有右节点 当我们清楚知道这些关系后,我们就可以通过一个数组建立起一个大根堆,核心思路为: 边建立边调整,我们遍历整个数组...当我们得到了这两种堆操作后,我们就可以完成我们堆排序了,算法思路很简单,因为难得我们已经说过了!

    57930

    堆排序算法

    排序---堆排序 一:定义 作为选择排序改进版,堆排序可以把每一趟元素比较结果保存下来,以便我们在选择最小/大元素对已经比较过元素做出相应调整。...二:堆排序算法 作为选择排序改进版,堆排序可以把每一趟元素比较结果保存下来,以便我们在选择最小/大元素对已经比较过元素做出相应调整。...堆排序是一种树形选择排序,在排序过程中可以把元素看成是一颗完全二叉树,每个节点都大(小)于它两个子节点,当每个节点都大于等于它两个子节点,就称为大顶堆,也叫堆有序; 当每个节点都小于等于它两个子节点...在构造有序堆,我们开始只需要扫描一半元素(n/2-1 ~ 0)即可,为什么?...发现以结点5为根子树不是最大堆,我们需要进行调整 ? 完成最大堆构建 ? 四:图解演示:堆排序(堆存储在数组中) 第一步:将最大值和最后一个元素交换 ? 第二步:将剩余结点再次进行堆构造 ?

    92710

    【数据结构】排序算法系列——堆排序(附源码+图解)

    堆排序 堆排序基于一种常见**[[二叉树]]结构**:堆 我们前面讲到选择排序,它在待排序n个记录中选择一个最小记录需要比较n一1次。...但是当我们根据[[二叉树]]遍历来进行输出,会发现同一个父节点子节点之间以及其中一个子节点子节点实际上是无序,例如60和10,它们之间是大于关系;而60子节点又都比10大,那么在遍历时候...所以堆实际上并不是完全有序,而我们使用堆排序这个算法,也并非是根据这样特征来进行。...我们可以看到,实际上堆排序核心思想就是将第一个根节点(最大值)与数组末尾元素来进行交换(目的是为了构建无需新开辟空间就能直接构建有序数组,末尾元素被交换后也不会影响大顶堆重新构建),然后重新构造堆...,那么此时第二个根节点就仅次于第一个根节点大小,这么以此类推,最终将所有节点根据大、次大、第三大顺序排序在数组中,那么也就成功构建出了有序数组

    8010

    为什么堆排序没有快速排序快?

    尽管这两种排序算法时间复杂度都是 O(nlogn),甚至堆排序比快速排序时间复杂度还要稳定,但是,在实际软件开发中,快速排序性能要比堆排序好,这是为什么呢?...罗列了两点要求,只要满足这两点,它就是一个堆。 堆是一个完全二叉树; 堆中每一个节点值都必须大于等于(或小于等于)其子树中每个节点值。 分别解释一下这两点。 第一点,堆必须是一个完全二叉树。...当我们删除堆顶元素之后,就需要把第二大元素放到堆顶,那第二大元素肯定会出现在左右子节点中。然后我们再迭代地删除第二大节点,以此类推,直到叶子节点被删除。 这里也画了一个分解图。...第一种建堆思路处理过程是从前往后处理数组数据,并且每个数据插入堆中,都是从下往上堆化。而第二种实现思路,是从后往前处理数组,并且每个数据都是从上往下堆化。...解答开篇 现在我们来看开篇问题,在实际开发中,为什么快速排序要比堆排序性能好? 觉得主要有两方面的原因。 第一点,堆排序数据访问方式没有快速排序友好。 对于快速排序来说,数据是顺序访问

    68230

    【排序篇】七大排序算法汇总

    以下图为例:以10为根左右子树,都满足小堆(堆)性质,只有根节点不满足,因此只需将根节点往下调,整合到合适位置就可以了。...回答:堆排序本质是选择排序,每次都要选择一个最大数到数组最后一位,那么问题就变成了如何选择最大数到数组最后一位,要找出堆中最大数就必须要用到大堆,因为大堆中最大数就在堆堆顶,通过一次次选择就可以将数组排序...++i) { printf("%d ", arr[i]); } return 0; } //打印结果: /* 2 3 4 5 6 7 8 32 50 60 65 70 100 */ 总结: 堆排序使用堆来选数...如此一来,就做到了把a[key]放到数组最终位置,因为此时a[key]左边都是小于它数,右边都是大于数,不就是a[key]最终位置嘛。...提问:为什么最终左右指针相遇数据一定小于a[key]? 回答:这就关系到左右指针谁先走问题。当我排升序时候一定要让右指针先走,右指针是找小嘛。

    6610

    【数据结构】堆排序与TOP-K问题

    1.堆排序 堆排序就是利用堆思想进行排序,总共分为两个步骤: 1.1 建堆 升序:建大堆 降序:建小堆 利用向下调整建堆 提问:为什么向下调整可以建堆 回答: 向下调整关键就除了要调节地方不对...以下图为例:以10为根左右子树,都满足小堆(堆)性质,只有根节点不满足,因此只需将根节点往下调,整合到合适位置就可以了。...回答:堆排序本质是选择排序,每次都要选择一个最大数到数组最后一位,那么问题就变成了如何选择最大数到数组最后一位,要找出堆中最大数就必须要用到大堆,因为大堆中最大数就在堆堆顶,通过一次次选择就可以将数组排序...主要步骤: 创建1000000个随机数,数值范围[0,999999] 创建一个大小为10小堆 开始进堆,如果当前数值大于堆顶数据,就将堆顶数值替换为当前数值,然后向下调整,让大数下沉。...个数,建小堆 //为了证明确实可以找到,我们需要自己设置10大于范围数,如果最后被找到就说明正确 a[5] = 1000000 + 1; a[55] = 1000000 + 2; a[99]

    6610

    常用排序算法代码兑现

    当我们详细研究了这些常用排序算法基本实现原理之后,是时候写出这些排序算法源代码了,也许这些代码在网上有更高效实现,不过下面写这些都是和之前说算法原理和图都解密切相关,一 一对应,主要是方便大家理解...使用了 Java 语言 和 C# 语言实现了这些算法,下面一 一列出。...,函数参数代表含义一般统一定义为: array: 待排序数组,类型为一维整形数组 n:元素个数 i:一般为外层循环索引,或表示排序区或未排序开始或结束索引 j :一般为内层循环索引,或表示未排序区或排序结束或开始索引...lo:数组计算区间开始索引 hi:数组计算区间结束索引 d :分组长度 k:分组索引 03 — 冒泡排序 //bubble sort public static void bubbleSort...,它选取一个轴点,每轮计算,凡是轴点移动都会空出一个位置,这个位置就是被调整后关键码所代替,经过这种调整后,一轮下来轴点前关键码都小于轴点,后大于

    691110

    堆排序

    因此,当我们完成堆构建之后,最大元素就在二叉树根节点上。此时,就该进行第二步了。...,但与第一次构建堆不同是,这次下沉范围应该把最后一个位置排除掉,因为那里放着最大元素,那个就是它最终位置。...不断重复这个过程,下沉排序范围也在一直缩小,最终只剩下了根节点自己,堆排序也就完成了。...堆(二叉堆):二叉堆是一组能够用堆有序二叉树排序元素,并在数组中按照层级存储(不适用数组第一个位置) 为什么不适用第一个位置:为了方便表示结点父结点和子结点。...只要不适用第一个结点也就是下标为0位置,那么任何一个元素,比如i父结点位置就是i/2向下取整,子结点位置就是2i和2i+1 堆有序:当一颗二叉树每个结点都大于等于他两个子结点,它被称为堆有序。

    31720

    【初阶数据结构】一文讲清楚 “堆” 和 “堆排序” -- 树和二叉树(二)(内含TOP-K问题)

    那么在本文中就会讲二叉树应用——“堆”,以及用对这个数据结构来实现堆数组进行排序功能。这个就是大名鼎鼎"堆排序"。...还会针对堆排序给大家再次拓展一个大家在以后编程道路上,会经常遇到一个实际问题:就是在一大堆数据中找出最大或最小前几个数,这个问题本质就是堆排序,我们也将这种问题,称为"TOP-K"问题。...小堆(小根堆):首先它得是一棵完全二叉树,其次它某一个节点都不小于其父节点(大于或等于其父节点)。这个就是小堆玩法。 还记得吗?完全二叉树可以使用顺序表来实现,这个是得益于完全二叉树特性决定。...,选取其中最大那个 //这里使用假设法,先假设左孩子大于右孩子值。...} int main() { int a[] = {5,2,3,7,1,9,8,10,6,4}; //堆排序 HeapSort(a,10); } 3.1 堆排序代码实现 现在来揭晓答案: void

    5310

    十大经典排序算法详解(三)-堆排序,计数排序,桶排序,基数排序

    因为每次重构成大根堆之后,根据大根堆特性,每个节点值一定大于左右孩子节点值,所以很明显大根堆根节点就是二叉树中值最大值同时也就是数组中最大值.所以重构成大根堆之后交换数组队头与队尾元素操作就是在将最大元素进行定位...,并且运行出来结果也和我预期一样,但是当我自己画图以后画到这张图时候就知道算法还是有BUG,这个BUG就是每次构建大根堆时候:我们的确能够在每次构建大根堆时候将最大元素挑选出来,但是,我们在挑选出当前最大元素之后...相信经过这样讲解之后,大家一定能够更好理解堆排序了. 复杂度分析: 理解完堆排序基本思想之后,我们就需要来分析一下他时间复杂度,空间复杂度....主要就是下面这几个步骤: 1.第一次遍历序列,找出序列中最大值以及最小值,然后根据最大值MAX与最小值MIN创建一个MAX-MIN+1长度数组.为什么创建这样长度数组呢,因为只有创建了这样长度数组...-桶排序 算法思想: 大家第一眼看到这个算法名字相信大家反应应该和我是一样,桶排序?

    57550

    C#堆排序算法

    堆排序中,我们首先将待排序数组构建成一个最大堆(或最小堆),然后逐个从堆中取出最大元素(或最小元素),将其放到数组末尾,同时重新调整剩余元素构成堆,直到堆中没有元素为止。...堆排序C#实现下面是一个堆排序算法C#实现示例:using System;class Program{ // 堆排序 static void HeapSort(int[] arr)...然后,我们使用HeapSort方法对数组进行排序。HeapSort方法首先通过Heapify方法将数组构建成一个最大堆,然后依次取出堆顶元素并调整堆,直到堆中没有元素。...例如,我们可以使用非递归方式来实现Heapify方法,以减少递归调用开销。...堆排序应用场景堆排序适用于各种规模数据排序,特别是当数据量较大

    76700

    【Java数据结构】优先级队列详解(二)

    ❤️❤️前言~ Hello, Hello~ 亲爱朋友们,这里是E绵绵呀✍️✍️。 如果你喜欢这篇文章,请别吝啬你点赞❤️❤️和收藏。如果你对内容感兴趣,记得关注以便不错过每一篇精彩。...当我们执行之前讲过三种任意一种构造方法,comparator都是null,所以在执行之后操作必会执行类似的siftupComparable方法,该方法源码如下 由此可知当我们priorityqueue...而当我们用自定义类比较,因为如上源码用了compareTo去比较,该方法是comparable类方法,如果该自定义类没有实施comparable接口,重写compareTo方法去比较该类 ,则会出现异常报错...堆特性保证了插入元素总是将当前最小元素添加到队列顶部。 遍历数组并插入优先队列:使用for循环遍历输入数组arr,将每个元素arr[i]添加到priorityQueue中。...我们通过堆这种数据结构去排序数组 就叫堆排序

    10510
    领券