左神算法笔记: 3. 比较器与堆

左神算法笔记之两个常用工具——对数器和比较器 一、对数器(验证算法是否正确,注意不是证明算法) ①准备一个随机数组发生器。 public static int[] generateRandomArray(int size, int value){ //产生[0,size]大小的随机整数数组((size+1)*Math.random(1)控制数组大小不会超过size) int[] arr = new int[(int)(size+1)*Math.random()]; for(int i=0; i < arr.length; i++){ / 阅读详情

algorithem/左神算法/基础

  1. 完全二叉树
    • 一种想象的数据结构
    • 实际是组数:
      1. 使用0节点
        • 左子节点:2i + 1
        • 右子节点:2i + 2
        • 父节点:( i - 1 ) / 2
      2. 不使用0节点
        • 左子节点:2i
        • 右子节点:2i + 1
        • 父节点:i / 2
  2. 堆排序 ::堆排序的额外空间复杂度为O(1)::
    1. 先让整个数组都变成大根堆结构,建立堆的过程:
      1. 从上到下的方法(生成heap),时间复杂度为O(N*logN)

        1. 把堆的最大值(root)和堆末尾的值交换,然后减少堆的大小,做一个heapify操作,再一直周而复始,时间复杂度为O(N*logN)
        2. 堆的大小减成0之后,排序完成
      2. 从下到上的方法(生成heap),时间复杂度为O(N)[image:4E5AA9A4-CF04-4821-848E-65A16FBD196C-6764-0001850E42CD133E/59D6BF48-9953-4AF6-B979-9D984B8EF721.png][image:8A018553-1C68-4B33-9A31-D203B6B6518B-6764-0001850517DDC2C8/356F41D8-FF55-4ED1-86FD-E4708A1FC823.png]

      3. 堆的大小减为0时,排序完成


    // 堆排序额外空间复杂度O(1)
    public static void heapSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        // O(N*logN)
        for (int i = 0; i < arr.length; i++) { // O(N)
            heapInsert(arr, i); // O(logN)
        }
        // O(N)
        // for (int i = arr.length - 1; i >= 0; i--) {
        // heapify(arr, i, arr.length);
        // }
        int heapSize = arr.length;
        swap(arr, 0, --heapSize);
        // O(N*logN)
        while (heapSize > 0) { // O(N)
            heapify(arr, 0, heapSize); // O(logN)
            swap(arr, 0, --heapSize); // O(1)
        }
    }

    // arr[index]刚来的数,往上
    public static void heapInsert(int[] arr, int index) {
        while (arr[index] > arr[(index - 1) / 2]) {
            swap(arr, index, (index - 1) / 2);
            index = (index - 1) / 2;
        }
    }

    // arr[index]位置的数,能否往下移动
    public static void heapify(int[] arr, int index, int heapSize) {
        int left = index * 2 + 1; // 左孩子的下标
        while (left < heapSize) { // 下方还有孩子的时候
            // 两个孩子中,谁的值大,把下标给largest
            // 1)只有左孩子,left -> largest
            // 2) 同时有左孩子和右孩子,右孩子的值<= 左孩子的值,left -> largest
            // 3) 同时有左孩子和右孩子并且右孩子的值> 左孩子的值, right -> largest
            int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
            // 父和较大的孩子之间,谁的值大,把下标给largest
            largest = arr[largest] > arr[index] ? largest : index;
            if (largest == index) {
                break;
            }
            swap(arr, largest, index);
            index = largest;
            left = index * 2 + 1;
        }
    }



  • 比较器
    1. 比较器的实质就是重载比较运算符
    2. 比较器可以很好的应用在特殊标准的排序上
    3. 比较器可以很好的应用在特殊标准排序的结构上[image:47A6D0E7-F190-499B-B99C-09A939BD3150-6764-00018AC3B67A7A2B/iShot2020-12-11 01.59.22.png]
    4. 写代码变得异常容易,还用于范型编程
    5. 需求:用户更改了某个值(影响排序),如何维持堆结构
      [image:B9823442-80A9-41A8-BC99-53101E2ECCAC-6764-00018ADA07DA0770/9AFE6CBA-D86F-4D81-8CFE-89B911E4DE29.png]
  • 实现:HashMap<T, Integer> indexMap 结构用来记录每个节点所在的位置,然后就可以通过对获得的Index进行一个向上冒泡的排序heapInsert(),和一个向下冒泡的排序heapify() ::两者实际只会执行一个::
/*
 * T一定要是非基础类型,有基础类型需求包一层
 */
public class HeapGreater<T> {

	private ArrayList<T> heap;
	private HashMap<T, Integer> indexMap;
	private int heapSize;
	private Comparator<? super T> comp;

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

	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++);
	}

	public T pop() {
		T ans = heap.get(0);
		swap(0, heapSize - 1);
		indexMap.remove(ans);
		heap.remove(--heapSize);
		heapify(0);
		return ans;
	}

	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);
		}
	}

	public void resign(T obj) {
		heapInsert(indexMap.get(obj));
		heapify(indexMap.get(obj));
	}

	// 请返回堆上的所有元素
	public List<T> getAllElements() {
		List<T> ans = new ArrayList<>();
		for (T c : heap) {
			ans.add(c);
		}
		return ans;
	}

	private void heapInsert(int index) {
		while (comp.compare(heap.get(index), heap.get((index - 1) / 2)) < 0) {
			swap(index, (index - 1) / 2);
			index = (index - 1) / 2;
		}
	}

	private void heapify(int index) {
		int left = index * 2 + 1;
		while (left < heapSize) {
			int best = left + 1 < heapSize && comp.compare(heap.get(left + 1), heap.get(left)) < 0 ? (left + 1) : left;
			best = comp.compare(heap.get(best), heap.get(index)) < 0 ? best : index;
			if (best == index) {
				break;
			}
			swap(best, index);
			index = best;
			left = index * 2 + 1;
		}
	}

	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);
	}
}
左神算法入门笔记 左神算法入门笔记0.特殊0.1 异或0.1.1 用异或做交换0.1.2 用异或找数1.排序算法1.1 简单排序1.1.1 选择排序1.1.2 冒泡排序1.1.3 插入排序1.2 特殊排序1.2.1 归并排序1.2.2 快速排序1.2.3 希尔排序1.3 桶排序1.3.1 计数排序1.3.2 基数排序1.4 堆排序1.5 题目1.5.1 小和问题 -- 改写归并排序1.5.2 对基本有序数组排序 -- 改写堆排序1.5.3 荷兰国旗问题 -- 快排前身1.5.4 比较器 -- 自定义结构排序2. 链表2.1 阅读详情

相关推荐

用itext读取PDF文件提取对应得字符串

一.maven导入jar包 <!--pdf解析start--> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.10</version...

zhanghua_chinese的博客 3695

八大排序复习

1.堆排 实现思路: 1.构建堆; 2.和最后一个值进行交换; 3.修改剩余的堆; 4.循环上述操作。 代码: // 堆排序额外空间复杂度O(1) public static void heapSort(int[] arr) { if (arr == null || arr.length < 2) { return; } // O(N*logN) // for (int i = 0; i < arr.le

wangke的博客 211

相衬成像介绍

相衬成像介绍

qq_41981768的博客 2910

(左神)数据结构与算法 ---- 详解堆排序、桶排序、基数排序及比较器内容结Day3(一)

让你快速掌握堆的概念和结构,以及堆排序的实现原理。本文用简单易懂的图文对《左神数据结构与算法》该部分内容进行总结与概括,并有实例题目进行练习巩固。

weixin_51201930的博客 508

ComfyUI的G-Dino模型加载器报错解决方案:从崩溃到重生

遇到G-Dino模型加载器报错不要慌,按照本文的步骤操作,99%的问题都能解决。模型文件正确下载到指定位置segment_anything节点安装完整且无冲突需要补充更多细节或故障排除方法吗?可以随时告诉我。

2301_78150483的博客 4020

IAR链接器配置文件(.icf)实战指南:从内存映射到代码布局

本文深入解析了IAR链接器配置文件(.icf)的核心作用与实战配置方法。作为嵌入式开发的“内存地图”,.icf文件精确控制代码与数据在Flash和RAM中的布局。文章从定义存储空间、划分区域、预留栈堆,到精确放置中断向量表、代码段及初始化控制,提供了完整的配置指南与避坑技巧,帮助开发者优化内存使用,解决链接错误,是掌握嵌入式系统底层内存管理的关键。

fun88的博客 916

(左神)数据结构与算法 ---- 详解堆排序、桶排序、基数排序及比较器内容结Day3(二)

本章内容详解--桶排序、基数排序以及实用性很强的比较器

weixin_51201930的博客 1011

JavaFx 教程

JavaFx 教程

2012年开始工作,全栈开发老兵,目前已是一个老师,分享这么多年的心得体会 784

class2 快排、堆排和比较器(左程云左神算法 初级笔记 2018)

class 2 荷兰国旗问题 给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。要求额外空间复杂度O(1),时间复杂度O(N) public class NetherlandsFlag { public static void netherlandsFlag(int[] arr,int L,int R,in...

quanquanya的博客 1549

【后量子密码】SPHINCS+ 算法(二):签名与验签(附源码分析)

本节介绍SPHINCS+ 算法的密钥生成、签名与验签。nnn:安全参数;www:Winternitz参数,WOTS+签名分解的基底;hhh:超树的高度;ddd:超树中子树的层数;kkk:FORS 树的数量;ttt:FORS 树的叶子节点数。

听雨草堂 4678

手把手教你学Simulink——基于经典PID控制的电机系统场景实例:BLDC电机PID电流控制策略仿真

*无刷直流电机(Brushless DC Motor, BLDC)**因其高效率、长寿命和低维护成本,在众多领域如家用电器、工业自动化、电动汽车等得到了广泛应用。为了实现对BLDC电机的有效控制,通常采用基于霍尔传感器或反电动势检测的换相技术,并结合电流闭环控制以提高系统的动态响应和稳定性。本教程将带你使用构建一个基于PID控制的BLDC电机电流控制策略仿真模型BLDC电机建模PID控制器设计与应用系统仿真与调试控制效果分析本文介绍了如何使用构建一个。

MHD0815的博客 196

左神算法课笔记

第一节 认识复杂度、对数器、二分法与异或运算 1. 认识复杂度 2. 对数器 对数器的实现方法: JAVA随机整数生成: 3. 二分法 复杂度为logn。 认识二分: 二分法中,为了安全,mid的下标最好用减法算出,以免加法溢出。位运算更快 常见的一些位运算写法: x^2 == x << 1; x^2 + 1 == x << 1 | 1; x/2 == x >> 1; 一个有

大魚的个人博客,如有不足,欢迎指正。 4142

记录Android Studio连接华为(nova)手机鸿蒙系统踩过的坑

鸿蒙系统的华为老机子比较麻烦,坑有点多,兄弟们加油!

沉迷单车的追风少年 7920

B站左神算法课学习笔记(P8):贪心

该文章是关于贪心算法,贪心策略模块的笔记。在某一标准下,优先考虑最满足标准的样本,最后考虑最不满足标准的样本,最终得到的一个答案的算法,叫做贪心算法。(即求局部最优解但是注意证明:局部最优解需推到整体最优解。

rzjslSe的博客 1149

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

左神算法笔记04

左神算法笔记04堆定义手撕堆堆的结构插入弹出最大值语言库自带的数据结构和自己写的数据结构对比比较器 堆 定义 堆必须是一个完全二叉树,而且必须是最大堆或最小堆。所以完全二叉树不一定是堆。 通过数组存储,脑补为二叉树的结构。 可以知道数组下标为iii的节点的父节点下标为i−12\frac {i-1} 22i−1​,左孩子节点下标为i∗2+1i*2+1i∗2+1,右孩子节点为 i∗2+2i*2+2i∗2+2。 手撕堆 接下来实现的是最大堆 堆的结构 public class heap() { private

xys946605的博客 261

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

左神算法讲堂笔记 09 由递归到动态规划

一、 有n个人希望把黄金分隔成 {a1,a2,a3,a4}, 希望代价最小。 代价是这么算的,例如长度是 7 ,分割成 3 4, 那么代价是7 。 逆向思维、哈夫曼编码 一开始的想法是,排序,每次切下来最大的。 但是 2 2 2 2 3 3 3 3 这种情况就pass了。 最后的做法是类似哈夫曼编码, 每次找出两个最小的, 合并,合并之后的点再加进去集合。 二、 有n个项目,对于第i个项目,需要花...

林鸿清的blog 1137

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

左神算法课笔记(七)贪心算法和暴力递归

给定一个整型数组arr,代表数值不同的纸牌排成一条线,玩家A和玩家B依次拿走纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家只能拿走最左或者最右的纸牌,玩家A和玩家B都聪明绝顶,请返回获胜者最后的分数。【会议问题】一个项目要占用一个会议室宣讲,会议室不能同时容纳两个项目的宣讲。如"abcd",打印"a" "ab" "abc" "abcd" "b" "bc" "bcd" "c" "cd" "d" ""1)先手拿的人拿的最大的分数为,选择最左或者最后的牌得到的分数与后手拿的分数的总和,选择分数最大的那一个。

qq_26012469的博客 1085

左神算法初级班笔记3:排序、队列、栈

文章目录01 | 补上节知识点1. 排序算法的稳定性及其汇总2. 介绍工程中的排序算法3. 比较器4. 桶排序、计数排序、基数排序5. 补充问题(年年考)02 | 第三节课1. 用数组结构实现大小固定的栈(难度:大厂一面)2. 用数组结构实现大小固定的队列(难度:大厂一面)3. 实现返回栈中最小元素的操作(难度:大厂一面)4. 如何仅用队列结构实现栈?(难度:大厂一面)5. 如何仅用栈结构实现队列?(难度:大厂一面) 01 | 补上节知识点 1. 排序算法的稳定性及其汇总 稳定性:排序前后,值相等的元素

aLinxi的博客 702

B站左神算法课学习笔记(P3):详解桶排序以及排序内容大总结

情况,每次都取到最大/最小值,一共展开 n 层递归,需要的空间复杂度为;情况,每次都取到中点值,相当于完全二叉树展开,需要的空间复杂度为注意:用迭代代替递归无法节省空间!因为节省不下来!递归实现了对于中点位置的存储,每层递归结束后才会释放相应资源,因为有了中点位置,快排才能借助递归实现。但是,若使用迭代,也需要手动记录中点位置,并使用栈结构,告诉计算机返回什么位置,以及该位置左右各是什么数。(自己的理解还是不太清楚,见谅)

rzjslSe的博客 1305

左神算法讲堂笔记 02 快排、堆排、桶排

1、荷兰国旗问题(快排的前导) 题意:把数组分成左边小于num,右边大于num,中间等于num,不需要有序 解法: 假设区间为[L , R] 维护一个左边小于区间,[L - less] ,维护一个右边大于区间 [more - R], 设当前下标为cur,不断把arr[ cur ]交换到左区间或者右区间即可。 这里的while写的很巧妙,每次只针对cur进行判断,把后面的换过来之后,cur不动,下一...

林鸿清的blog 540

左神算法笔记01——排序算法

十大排序算法 选择排序 遍历n次,每次找出i到n-1最小的值,和i位置的值做交换 时间复杂度为o(n²) public static void swap(int[] arr,int i,int j){ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } public static void selectionSort(int[] arr){ if(arr == null |

upset_poor的博客 971

左神算法笔记-3 详解桶排序以及排序内容大总结

听了好久,晚上听可太困了 离散数学课上听了一半,算法果然很顶! 讲了快排的空间复杂度,详解堆排序,桶排序等 2021年9月28日 19点59分 1、快速排序的空间复杂度(0) 空间复杂度为O(logn) 分为最坏和最好情况: Ⅰ.最坏情况 当每次划分值都是最大的数据,此时每次都要保存划分的位置,要调用N层,每层申请一个额外空间来存储划分值使得需要的额外空间复杂度就是O(N)即每个数字都要存起来 直到最后一层开始往回返。 Ⅱ.最好情况 当每次的划分值较为合适(接近中点值)时,就能出现较好的情况,此时空间复杂度

m0_51183169的博客 324

左神算法初级班三 笔记

排序的稳定性:在排序过程中,如果任意两个元素的用于排序的基准值相同,排完序之后,如果他们的相对顺序不变,则称排序稳定,否则不稳定。 实际业务过程中我们有时候可能希望保留原始的一些信息(和相对次序有关) 不能做到稳定性的排序算法:堆排序、快速排序、二分插入排序 可以做到稳定性的排序算法:冒泡排序、朴素插入排序、归并排序 Java中的sort具有稳定性,当针对类型是基础数值类型如int、dou...

The Shawshank Redemption 184

左神算法整理笔记04

左神算法整理笔记04

xlshi1996的博客 157

左神算法笔记(三)——桶排序及排序总结

排序稳定性 排序稳定性在于对于相同的数值,能否将相同数据原本的顺序保证不交换。 1(0)2(1)2(2)1(3)——>排序:1(0)1(3)2(1)2(2) 针对于原始的信息排序,之前的顺序可能本身存在着一定的意义,排序稳定性会使得重新排序之后依旧维持着之前排序的特点。 工程中的综合排序 1.程序判断数组是否为基础类型,若为int,short,char,double,float基础类型,则会...

848

【左神算法】IPO问题

502. IPO IPO 难度困难39 假设 力扣(LeetCode)即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。 给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。

芝兰生于深谷,不以无人而不芳 754
上一篇: 左神算法笔记: 2. 线段树(区间修改数)
下一篇: 链表中环的问题,寻找环的起点
傻梨吃渣梨
博客等级 码龄8年 0粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值