堆排序及常见面试题

news2024/10/7 16:21:27

请添加图片描述
⭐️前言⭐️

本篇文章记录堆排序以及对应的一些练习。

🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传GitHub


请添加图片描述

📍内容导读📍

  • 🍅1.堆排序实现
  • 🍅2.线段最大重合问题
  • 🍅3.加强堆的实现

🍅1.堆排序实现

实现思路:
1.首先先建大堆
2.建好堆后,利用堆的性质完成排序
3.将堆顶元素与堆位元素互换,那么堆尾位置元素就是堆中的最大元素,并将堆顶元素向下调整,继续保持堆结构。
4.持续相同操作,直到到堆顶位置,此时堆中元素变为升序。

代码实现:

public class HeapSort {
    public static void heapSort(int[] array) {
        createBigHeap(array);
        int end=array.length-1;
        while (end>=0) {
            swap(array,0,end);
            shiftDown(array,0,end);
            end--;
        }
    }
    
    private static void shiftDown(int[] array,int parent,int len) {
        // 保证有左孩子
        int child=2*parent+1;
        while (child<len) {
            // 如果有右孩子,左右孩子比较,child记录较大值的下标
            if(child+1<len&&array[child]<array[child+1]) {
                child++;
            }
            if(array[child]>array[parent]) {
                swap(array,child,parent);
                // 继续向下调整
                parent=child;
                child=2*parent+1;
            }else {
                break;
            }
        }
    }

    private static void swap(int[] array,int i,int j) {
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }
    private static void createBigHeap(int[] array) {
        // 先找到最后一棵子树的父节点,让每棵子树成为大顶堆
        for(int parent=(array.length-1-1)/2;parent>=0;parent--) {
            shiftDown(array,parent,array.length);
        }
    }
}

🍅2.线段最大重合问题

题目:
给定很多线段,每个线段都有两个数[start, end],
表示线段开始位置和结束位置,左右都是闭区间
规定:
1)线段的开始和结束位置一定都是整数值
2)线段重合区域的长度必须>=1
返回线段最多重合区域中,包含了几条线段

题解思路:
1.首先通过比较器,将所有线段基于线段的起始位置进行排序,然后来求每条线段的最大重复线段数。
2.利用小根堆(小根堆存储每条线段的结束位置),每次到达新线段时,将小根堆中比新线段起始位置小的数弹出(弹出的线段是起始位置和结束位置都比新线段其实位置小的线段,不可能有重复),并将新线段的结束位置放入小根堆,此时小根堆中代表的线段就是有公共重合区域的线段,返回heap.size()就是重复线段数。
3.每条线段都进行这样的操作,返回heap.size()中最大的max,就表示线段最多重合区域中,包含的线段数。

代码实现:

public class CoverMax {
    static class Line {
        public int start;
        public int end;

        public Line(int start, int end) {
            this.start = start;
            this.end = end;
        }
    }

    static int maxCover(int[][] m) {
        Line[] lines=new Line[m.length];
        for (int i = 0; i < m.length; i++) {
            lines[i]=new Line(m[i][0],m[i][1]);
        }
        Arrays.sort(lines, new Comparator<Line>() {
            @Override
            public int compare(Line o1, Line o2) {
                return o1.start-o2.start;
            }
        });
        // Arrays.sort(lines,(a,b)->a.start-b.start);  // 语法糖
        PriorityQueue<Integer> heap=new PriorityQueue<>();
        int max=0;
        for (int i = 0; i < lines.length; i++) {
            while (!heap.isEmpty()&&heap.peek()<=lines[i].start) {
                heap.poll();
            }
            heap.add(lines[i].end);
            max=Math.max(max,heap.size());
        }
        return max;
    }
}

🍅3.加强堆的实现

是对于普通堆结构的改写,增添了一些普通堆不具有的功能

public class HeapGreater<T> {
    private ArrayList<T> heap;
    private HashMap<T,Integer> indexMap;  // 用于加强堆结构中的反向索引操作
    private int heapSize;
    private Comparator<? super T> comp;

    public HeapGreater(Comparator<? super T> comp) {
        heap=new ArrayList<>();
        indexMap=new HashMap<>();
        heapSize=0;
        this.comp = comp;
    }

    // 判断堆是否为空
    public boolean isEmpty() {
        return heapSize==0;
    }
    // 返回堆大小
    public int size() {
        return heapSize;
    }
    // 判断堆中是否包含某个元素
    public boolean contains(T obj) {
        return indexMap.containsKey(obj);
    }
    // 返回堆顶元素
    public T peek() {
        return heap.get(0);
    }
    // 堆中新增元素
    public void push(T obj) {
        heap.add(obj);
        indexMap.put(obj,heapSize);
        heapInsert(heapSize);
        heapSize++;
    }
    // 堆中插入新元素,向上调整新元素
    private void heapInsert(int child) {
        int parent=(child-1)/2;
        while (child>0) {
            if(comp.compare(heap.get(child),heap.get(parent))<0) {
                swap(child,parent);
                child=parent;
                parent=(child-1)/2;
            }else {
                break;
            }
        }
    }

    private void swap(int i, int j) {
        T o1=heap.get(i);
        T o2=heap.get(j);
        heap.set(i,o2);
        heap.set(j,o1);
        indexMap.put(o2,i);
        indexMap.put(o1,j);
    }
    // 弹出堆顶元素
    public T pop() {
        T ans=heap.get(0);
        swap(0,heapSize-1);
        indexMap.remove(ans);
        heap.remove(--heapSize);
        shiftDown(0);
        return ans;
    }
    // 小根堆向下调整
    private void shiftDown(int parent) {
        int child=2*parent+1;
        while (child<heapSize) {
            if(child+1<heapSize&&comp.compare(heap.get(child+1),heap.get(child))<0) {
                child++;
            }
            if(comp.compare(heap.get(child),heap.get(parent))<0) {
                swap(child,parent);
                parent=child;
                child=2*parent+1;
            }else {
                break;
            }
        }
    }
    // 去除某个元素
    public void remove(T obj) {
        T replace=heap.get(heapSize-1);
        int index=indexMap.get(obj);
        indexMap.remove(obj);
        heap.remove(--heapSize);
        if(obj!=replace) {
            heap.set(index,replace);
            indexMap.put(replace,index);
            resign(replace);
        }
    }

    private void resign(T obj) {
        heapInsert(indexMap.get(obj));
        shiftDown(indexMap.get(obj));
    }
    
    // 返回堆上所有元素
    public List<T> getAllElements() {
        List<T> ans=new ArrayList<>();
        for(T c:heap) {
            ans.add(c);
        }
        return ans;
    } 
}

⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

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

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

相关文章

硬“核”数字员工:中国核能行业协会携手实在智能,成功举办核能行业数字化实战培训

导语&#xff1a; 近期&#xff0c;中国核能行业协会携手实在智能&#xff0c;成功举办核能行业数字化实战培训&#xff0c;通过理论学习和参与实践&#xff0c;学员们亲手打造出一个个硬“核”数字员工。 十多张表格快速切换&#xff0c;无数串数字在面前跳动&#xff0c;上岗…

数据中台建设:千万级的瀑布式,和十万级的迭代式,你会选择哪一个?

中台十年&#xff0c;再看已成桑田。 最初&#xff0c;为了解决互联网行业快速发展催生出的海量数据累积和碎片化问题&#xff0c;企业开始尝试将数据整合到一个中央平台&#xff0c;以提高数据的使用效率和管理水平&#xff0c;中台建设雏形初现。巨头领跑之下&#xff0c;从…

刷题笔记【7】| 快速刷完67道剑指offer(Java版)

本文已收录于专栏 &#x1f33b; 《刷题笔记》 文章目录 前言&#x1f3a8; 1、二叉树中和为某一值的路径题目描述思路&#xff08;深度优先搜索&#xff09; &#x1f3a8; 2、复杂链表的复制题目描述思路 &#x1f3a8; 3、二叉搜索树与双向链表题目描述思路 &#x1f3a8; 4…

【蓝桥杯省赛真题20】python二次加密 青少年组蓝桥杯比赛python编程省赛真题解析

目录 python二次加密 一、题目要求 1、编程实现 2、输入输出 二、解题思路

STATS 782 - Numerical Computation

文章目录 一、Simple Graphics1. 用 plot&#xff08;&#xff09;函数画图 二、Optimization1. 简单求最值2. Interpolation&#xff08;插值&#xff09;3. optim&#xff08;&#xff09;函数 一、Simple Graphics 1. 用 plot&#xff08;&#xff09;函数画图 x 和 y&…

Linux常用命令——iptables命令

在线Linux命令查询工具 iptables Linux上常用的防火墙软件 补充说明 iptables命令是Linux上常用的防火墙软件&#xff0c;是netfilter项目的一部分。可以直接配置&#xff0c;也可以通过许多前端和图形界面配置。 补充说明 - 语法选项基本参数 - 命令选项输入顺序工作机制…

【java】CGLIB动态代理原理

文章目录 1. 简介2. 示例3. 原理4. JDK动态代理与CGLIB动态代理区别&#xff08;面试常问&#xff09; 1. 简介 CGLIB的全称是&#xff1a;Code Generation Library。 CGLIB是一个强大的、高性能、高质量的代码生成类库&#xff0c;它可以在运行期扩展Java类与实现Java接口&a…

【SAP Abap】X-DOC:SE43 - SAP 用户菜单定义

X-DOC&#xff1a;SE43 - SAP 用户菜单定义 1、菜单结构2、菜单配置3、菜单自定义4、实践演示 1、菜单结构 SAP的菜单栏&#xff0c;支持按层次结构配置&#xff0c;包括以下两个概念&#xff1a; &#xff08;1&#xff09;菜单项&#xff1a;具体的一个菜单目录或菜单项&…

爬虫日常-12306自动购票程序

文章目录 前言页面分析代码设计 前言 hello兄弟们&#xff0c;最近在钻研新鲜知识&#xff0c;一不留神没想起来更新。今天我们顺着前面几篇文章完整的写出一篇12306的自动购票软件。 首先把我们已经写完的前期步骤代码再顺一遍 from selenium.webdriver import Chrome from…

阿里大佬都在熬夜肝的Java程序优化笔记,程序性能提高了5倍!

前言 此笔记从软件设计、编码和JVM等维度阐述性能优化的方法和技巧&#xff0c;分享资深架构师Java程序性能优化的宝贵经验&#xff0c;专注于Java应用程序的优化方法、技巧和思想&#xff0c;并深度剖析JDK部分的实现。具有较强的层次性和连贯性&#xff0c;深入剖析软件设计…

Word控件Spire.Doc 【脚注】教程(5):单词脚注的位置与数字格式

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

1.19 从0开始学习Unity游戏开发--扩展编辑器

在之前的篇章里面&#xff0c;我们一直在编辑器里面干活&#xff0c;然后做好资源的编辑和代码开发后&#xff0c;我们可以直接在编辑器内点击那个播放按钮就能真实的把游戏跑起来&#xff0c;但是有时候&#xff0c;我们可能希望在菜单里面加个按钮&#xff0c;这样我们可以直…

C++ STL学习之【容器适配器】

✨个人主页&#xff1a; 夜 默 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 A year from now you may wish you had started today. 明年今日&#xff0c;你会希望此时此刻的自己已经开始行动了。 文章目录 &#x1f307;前言&a…

内存泄漏动态检测(valgrind)

初步判断是否有泄漏 Linux 内存性能优化 —— 高内存使用及内存泄漏排查 比如该文的介绍&#xff0c;需要初步了解top free -h等命令&#xff1b; 主要看free 内存泄漏检测方法&#xff1a; 静态我常用的是cppcheck&#xff1b; 动态的 Linux下内存泄漏定位方法 这个文章…

Node.js 一:基础

1.node.js是什么&#xff1a; 2.node.js的作用&#xff1a; 1.服务器应用&#xff1a;b站.. 2.开发工具类应用&#xff1a;webpack&#xff0c;bable等等 3.桌面端应用&#xff1a;vscode&#xff0c;postman等 这些应用都是基于electron框架开发&#xff0c;electron基于node…

【设计模式】23种设计模式之行为型模式

一、模板方法模式 1、豆浆制作问题 编写制作豆浆的程序&#xff0c;说明如下: 1&#xff09;、制作豆浆的流程 选材--->添加配料--->浸泡--->放到豆浆机打碎 2&#xff09;、通过添加不同的配料&#xff0c;可以制作出不同口味的豆浆 3&#xff09;、选材、浸泡和放…

拥抱还是革命,ChatGPT时代 AI专家给出15条科研生存之道

来源&#xff1a;专知 微信号&#xff1a;Quan_Zhuanzhi 你是学术机构的人工智能研究员吗?你是否担心自己无法应对当前人工智能的发展步伐?您是否觉得您没有(或非常有限)访问人工智能研究突破所需的计算和人力资源?你并不孤单; 我们有同样的感觉。越来越多的人工智能学者不…

vuepress-yarn-nodes-静态网页_个人博客搭建

nodes官网&#xff1a;https://nodejs.org/en 先下载nodes进行安装&#xff0c;一般nodes会自带包管理器npm&#xff0c;注意npm与nodes的对应关系&#xff0c;除了npm之外还有yarn包管理器&#xff0c;一般会用npm安装这个包 npm install --global yarnnpm降低版本的方法 np…

LeetCode 1026. 节点与其祖先之间的最大差值

【LetMeFly】1026.节点与其祖先之间的最大差值 力扣题目链接&#xff1a;https://leetcode.cn/problems/maximum-difference-between-node-and-ancestor/ 给定二叉树的根节点 root&#xff0c;找出存在于 不同 节点 A 和 B 之间的最大值 V&#xff0c;其中 V |A.val - B.val…

《花雕学AI》24:如何用万能Prompt公式与ChatGPT进行高效的对话测试

引言 你是否想要与人工智能进行有趣、有价值、有说服力的对话&#xff1f;你是否想要使用ChatGPT这个强大而灵活的对话生成器来创造出任何类型和主题的对话&#xff1f;如果是这样&#xff0c;那么你需要了解一个简单而强大的工具&#xff0c;就是万能Prompt公式。 万能Promp…