(归并排序 快排 堆)

文章目录

    • 归并排序
        • 递归方法实现
        • 非递归方法实现
        • 求数组的小和
        • 求数组的降序对个数
    • 快排
        • 荷兰国旗问题(Partition过程)
        • 快排1.0
        • 快排2.0
        • 快排3.0
        • 大根堆
        • 堆排序
        • 使用堆排序

归并排序

递归方法实现

public class Code01_MergeSort {// 递归方法实现public static void mergeSort1(int[] arr) {if (arr == null || arr.length < 2) {return;}process(arr, 0, arr.length - 1);}// 请把arr[L..R]排有序// l...r N// T(N) = 2 * T(N / 2) + O(N)// O(N * logN)public static void process(int[] arr, int L, int R) {if (L == R) { // base casereturn;}int mid = L + ((R - L) >> 1);process(arr, L, mid);process(arr, mid + 1, R);merge(arr, L, mid, R);}public static void merge(int[] arr, int L, int M, int R) {int[] help = new int[R - L + 1];int i = 0;int p1 = L;int p2 = M + 1;while (p1 <= M && p2 <= R) {help[i++] = arr[p1] <= arr[p2] ? arr[p1++] : arr[p2++];}// 要么p1越界了,要么p2越界了while (p1 <= M) {help[i++] = arr[p1++];}while (p2 <= R) {help[i++] = arr[p2++];}for (i = 0; i < help.length; i++) {arr[L + i] = help[i];}}}

非递归方法实现

public static void mergeSort2(int[] arr) {if (arr == null || arr.length < 2) {return;}int N = arr.length;// 步长int mergeSize = 1;while (mergeSize < N) { // log N// 当前左组的,第一个位置int L = 0;while (L < N) {if (mergeSize >= N - L) {break;}int M = L + mergeSize - 1;int R = M + Math.min(mergeSize, N - M - 1);merge(arr, L, M, R);L = R + 1;}// 防止溢出if (mergeSize > N / 2) {break;}mergeSize <<= 1;}
}	

求数组的小和

在一个数组中,一个数数左边比它小的数的总和,叫数的小和,所有数的小和累加起来,叫数组的小和
(一个数右边有多少个数比他

public class Code02_SmallSum {public static int smallSum(int[] arr) {if (arr == null || arr.length < 2) {return 0;}return process(arr, 0, arr.length - 1);}// arr[L..R]既要排好序,也要求小和返回// 所有merge时,产生的小和,累加// 左 排序   merge// 右 排序  merge// mergepublic static int process(int[] arr, int l, int r) {if (l == r) {return 0;}// l < rint mid = l + ((r - l) >> 1);return process(arr, l, mid) + process(arr, mid + 1, r) + merge(arr, l, mid, r);}public static int merge(int[] arr, int L, int m, int r) {int[] help = new int[r - L + 1];int i = 0;int p1 = L;int p2 = m + 1;int res = 0;while (p1 <= m && p2 <= r) {res += arr[p1] < arr[p2] ? (r - p2 + 1) * arr[p1] : 0;help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];}while (p1 <= m) {help[i++] = arr[p1++];}while (p2 <= r) {help[i++] = arr[p2++];}for (i = 0; i < help.length; i++) {arr[L + i] = help[i];}return res;}
}

求数组的降序对个数

(一个数左边有多少个数比他

public class Code03_ReversePair {public static int reverPairNumber(int[] arr) {if (arr == null || arr.length < 2) {return 0;}return process(arr, 0, arr.length - 1);}// arr[L..R]既要排好序,也要求逆序对数量返回// 所有merge时,产生的逆序对数量,累加,返回// 左 排序 merge并产生逆序对数量// 右 排序 merge并产生逆序对数量public static int process(int[] arr, int l, int r) {if (l == r) {return 0;}// l < rint mid = l + ((r - l) >> 1);return process(arr, l, mid) + process(arr, mid + 1, r) + merge(arr, l, mid, r);}public static int merge(int[] arr, int L, int m, int r) {int[] help = new int[r - L + 1];int i = help.length - 1;int p1 = m;int p2 = r;int res = 0;while (p1 >= L && p2 > m) {res += arr[p1] > arr[p2] ? (p2 - m) : 0;help[i--] = arr[p1] > arr[p2] ? arr[p1--] : arr[p2--];}while (p1 >= L) {help[i--] = arr[p1--];}while (p2 > m) {help[i--] = arr[p2--];}for (i = 0; i < help.length; i++) {arr[L + i] = help[i];}return res;}
}

时间复杂度 N*logN

快排

荷兰国旗问题(Partition过程)

public class Code02_PartitionAndQuickSort {public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}// arr[L..R]上,以arr[R]位置的数做划分值// <= X > X// <= X Xpublic static int partition(int[] arr, int L, int R) {if (L > R) {return -1;}if (L == R) {return L;}int lessEqual = L - 1;int index = L;while (index < R) {if (arr[index] <= arr[R]) {swap(arr, index, ++lessEqual);}index++;}swap(arr, ++lessEqual, R);return lessEqual;}// arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值// <arr[R] ==arr[R] > arr[R]public static int[] netherlandsFlag(int[] arr, int L, int R) {if (L > R) { // L...R L>Rreturn new int[] { -1, -1 };}if (L == R) {return new int[] { L, R };}int less = L - 1; // < 区 右边界int more = R; // > 区 左边界int index = L;while (index < more) { // 当前位置,不能和 >区的左边界撞上if (arr[index] == arr[R]) {index++;} else if (arr[index] < arr[R]) {
//				swap(arr, less + 1, index);
//				less++;
//				index++;						swap(arr, index++, ++less);} else { // >swap(arr, index, --more);}}swap(arr, more, R); // <[R]   =[R]   >[R]return new int[] { less + 1, more };}}

快排1.0

O(N^2)
<= 和> 两个区域

	public static void quickSort1(int[] arr) {if (arr == null || arr.length < 2) {return;}process1(arr, 0, arr.length - 1);}public static void process1(int[] arr, int L, int R) {if (L >= R) {return;}// L..R partition arr[R] [ <=arr[R] arr[R] >arr[R] ]int M = partition(arr, L, R);process1(arr, L, M - 1);process1(arr, M + 1, R);}

快排2.0

O(N^2)
相比于1.0,< = > 三个区域

	public static void quickSort2(int[] arr) {if (arr == null || arr.length < 2) {return;}process2(arr, 0, arr.length - 1);}// arr[L...R] 排有序,快排2.0方式public static void process2(int[] arr, int L, int R) {if (L >= R) {return;}// [ equalArea[0]  ,  equalArea[0]]int[] equalArea = netherlandsFlag(arr, L, R);process2(arr, L, equalArea[0] - 1);process2(arr, equalArea[1] + 1, R);}

快排3.0

O(NlogN)
相比于2.0,在数组中随机选择一个数,和arr[R]交换,开始2.0

	public static void quickSort3(int[] arr) {if (arr == null || arr.length < 2) {return;}process3(arr, 0, arr.length - 1);}public static void process3(int[] arr, int L, int R) {if (L >= R) {return;}swap(arr, L + (int) (Math.random() * (R - L + 1)), R);int[] equalArea = netherlandsFlag(arr, L, R);process3(arr, L, equalArea[0] - 1);process3(arr, equalArea[1] + 1, R);}

在这里插入图片描述

结构上:完全二叉树

大根堆

public class Code02_Heap {public static class MyMaxHeap {private int[] heap;private final int limit;private int heapSize;public MyMaxHeap(int limit) {heap = new int[limit];this.limit = limit;heapSize = 0;}public boolean isEmpty() {return heapSize == 0;}public boolean isFull() {return heapSize == limit;}public void push(int value) {if (heapSize == limit) {throw new RuntimeException("heap is full");}heap[heapSize] = value;// value heapSizeheapInsert(heap, heapSize++);}// 用户此时,让你返回最大值,并且在大根堆中,把最大值删掉// 剩下的数,依然保持大根堆组织public int pop() {int ans = heap[0];swap(heap, 0, --heapSize);heapify(heap, 0, heapSize);return ans;}// 新加进来的数,现在停在了index位置,请依次往上移动,// 移动到0位置,或者干不掉自己的父亲了,停!private void heapInsert(int[] arr, int index) {// [index] [index-1]/2// index == 0while (arr[index] > arr[(index - 1) / 2]) {swap(arr, index, (index - 1) / 2);index = (index - 1) / 2;}}// 从index位置,往下看,不断的下沉// 停:较大的孩子都不再比index位置的数大;已经没孩子了private void heapify(int[] arr, int index, int heapSize) {int left = index * 2 + 1;while (left < heapSize) { // 如果有左孩子,有没有右孩子,可能有可能没有!// 把较大孩子的下标,给largestint largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;largest = arr[largest] > arr[index] ? largest : index;if (largest == index) {break;}// index和较大孩子,要互换swap(arr, largest, index);index = largest;left = index * 2 + 1;}}private void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}}
}

堆排序

public class Code03_HeapSort {// 堆排序额外空间复杂度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 -> largestint largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;// 父和较大的孩子之间,谁的值大,把下标给largestlargest = arr[largest] > arr[index] ? largest : index;if (largest == index) {break;}swap(arr, largest, index);index = largest;left = index * 2 + 1;}}public static void swap(int[] arr, int i, int j) {int tmp = arr[i];arr[i] = arr[j];arr[j] = tmp;}
}

使用堆排序

已知一个几乎有序的数组。几乎有序是指,如果把数组排好顺序的话,每个元素移动的距离一定不超过k,并且k相对于数组长度来说是比较小的(时间复杂度:N*logK)。

// 默认小根堆
PriorityQueue<Integer> heap = new PriorityQueue<>();
public class Code04_SortArrayDistanceLessK {public static void sortedArrDistanceLessK(int[] arr, int k) {if (k == 0) {return;}// 默认小根堆PriorityQueue<Integer> heap = new PriorityQueue<>();int index = 0;// 0...K-1for (; index <= Math.min(arr.length - 1, k - 1); index++) {heap.add(arr[index]);}int i = 0;for (; index < arr.length; i++, index++) {heap.add(arr[index]);arr[i] = heap.poll();}while (!heap.isEmpty()) {arr[i++] = heap.poll();}}
}

在这里插入图片描述

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

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

相关文章

亦云小组KTV点歌系统简介

20级青鸟四班 亦云小组指导老师&#xff1a;穆老师 班主任&#xff1a;佟老师小组成员&#xff1a;组长&#xff1a;靳天宇组员&#xff1a;王晓丹 谢佳泽 王睿志 蒲璐颖 张铨政目录&#xff1a;1.首页 2.项目前台 3..项目后台总结&#xff1a;本次KTV项目总结。总体来说&…

学习手记(2018/7/14~2018/7/18)——快乐纪中

2018/7/14&#xff1a;普通的纪中一天 儿子兄弟表示法 将一颗多叉树转换为二叉树的方法&#xff0c;左子节点连原树的第一个儿子&#xff0c;右子节点连原树的右边的兄弟 适用范围&#xff1a;树形dp 数位dp常见方法 状态压缩 分类讨论记忆法&#xff08;记忆化搜索&#x…

Entity Framework Core 2.0 特性介绍和使用指南

前言 这是.Net Core 2.0生态生态介绍的最后一篇&#xff0c;EF一直是我喜欢的一个ORM框架&#xff0c;随着版本升级EF也发展到EF6.x&#xff0c;Entity Framework Core是一个支持跨平台的全新版本&#xff0c;可以用三个词来概况EF Core的特点&#xff1a;轻量级、可扩展、跨平…

图解elasticsearch原理转载自

转载自 图解elasticsearch原理 版本 elasticsearch版本: elasticsearch-2.x 内容 图解ElasticSearch 云上的集群 集群里的盒子 云里面的每个白色正方形的盒子代表一个节点——Node。 节点之间 在一个或者多个节点直接&#xff0c;多个绿色小方块组合在一起形成一个Elas…

零云九歌小组KTV点歌系统简介

指导老师&#xff1a;穆老师 班主任&#xff1a;佟老师小组成员&#xff1a;组长&#xff1a;张炜林 副组长&#xff1a;李钰组员&#xff1a;郑宪佳 宋翔 李兆勋 杜庆霖零云九歌目录&#xff1a;1.首页 2.项目前台 3..项目后台总结&#xff1a;本次KTV项目总结。总体来说&am…

( 前缀树 计数排序 基数排序 )

文章目录前缀树桶排序计数排序基数排序前缀树 实现一&#xff1a; public class Code01_TrieTree {public static class Node1 {public int pass;public int end;public Node1[] nexts;// char tmp b (tmp - a)public Node1() {pass 0;end 0;// 0 a// 1 b// 2 c…

P3387-【模板】缩点【tarjan,强联通分量,DAGdp】

正题 评测记录&#xff1a; https://www.luogu.org/recordnew/lists?uid52918&pidP3387 大意 一个有向图。每个点有权值&#xff0c;但每个值只能取一次&#xff0c;每条边可以重复走&#xff0c;求一条路径使值最大。 解题思路 用tarjan求出每一个强联通分量&#xf…

Orleans简单配置

话说曾几何时,我第一次看到xml文件,心中闪过一念想:"这<>是什么鬼?"…用ini或者json多简单易懂,现在发觉作为配置文件,json有赶超xml的趋势.不过xml用多了,也觉得顺眼多了.不觉得<>难看了,反而它能折叠让我觉得组织起来也更方便了.这说明一个道理:不是你…

say小组KTV点歌系统简介

指导老师&#xff1a;穆老师 班主任&#xff1a;佟老师小组成员&#xff1a;组长&#xff1a;焦文宇 组员&#xff1a;窦倩 王晓凤 巩固 石虹蔓 田锋目录&#xff1a;1.首页 2.项目前台 3..项目后台总结&#xff1a;从5月25号开始的到6月10号结束&#xff0c;这期间我们遇…

Java虚拟机必学之四大知识要点,附学习资料

转载自 Java虚拟机必学之四大知识要点&#xff0c;附学习资料 作为一位 Java 程序员&#xff0c;在尽情享受 Java 虚拟机带来好处的同时&#xff0c;我们还应该去了解和思考“这些技术特性是如何实现的”&#xff0c;去了解最底层的原理。只有熟悉 JVM&#xff0c;你才能在遇…

RabbitMQ消息可靠性 (投递+消费)

文章目录Rabbitmq的消息可靠性投递Rabbitmq的消息可靠性投递confirmCallbackRabbitmq的消息可靠性投递returnCallbackRabbitmq的消息确机制ACKRabbitmq的消息可靠性投递 什么是消息的可靠性投递 保证消息百分百发送到消息队列中去 1 保证mq节点成功接受消息&#xff0c;消息发…

jzoj4024-石子游戏【SG函数,博弈论】

正题 大意 有n堆石头&#xff0c;每堆石头有aiai个每次可以拿走一堆或者Y个&#xff08;仅当gcd(Y,ai)1gcd(Y,ai)1&#xff09;。拿走最后一堆石头的人就赢了&#xff0c;两个人都是聪明绝顶的。 解题思路 考虑构建SG函数&#xff1a; SG(x)mex(SG(x−y)(gcd(x,y)1) υ …

程序配置amp;amp;ConfigurationManager

配置组件是.net framework中非常常用的功能。在创建.net framework 工程时&#xff0c;系统不仅会自动生成app.config文件&#xff0c;而且还提供了非常强大的访问类库。但是这些好东西&#xff0c;在.net core 2.0中已经不复存在&#xff0c;至少说没有.net framework 中那么完…

既然参与,那就做好,我相信我们是最棒的!!!

‍‍大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。今天是3班的KTV项目答辩&#xff0c;也是20级的最后一个班级&#xff0c;连续6天的KTV项目答辩终于告一段落。回顾各班所做的项目&#xff0c;通过我自己参与点评的以及从班内参观同学…

又发生频繁FGC,这次是谁的锅

转载自 又发生频繁FGC&#xff0c;这次是谁的锅 这是笨神JVMPocket群里一位名为"云何*住"的同学提出来的问题&#xff0c;问题现象是CPU飙高并且频繁FullGC。 重现问题 这位同学的业务代码比较复杂&#xff0c;为了简化业务场景&#xff0c;笔者将其代码压缩成如…

jzoj4025-找回密码【后缀自动机】

正题 大意 一个字符串&#xff0c;要求第k小的子串。 解题思路 先建立一个后缀自动机&#xff0c;然后用一个numinum_inumi​表示第iii个节点的可以到达的点所表示的子串总和&#xff0c;然后从第1号点开始查找&#xff0c;判断一下找到第k小所在的节点后&#xff0c;然后查找…

三个剩两个,两个剩一个,最后一个都没剩下。

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。今天文章的标题本来是&#xff1a;“从未见过如此不要脸耍无赖的人&#xff01;&#xff01;&#xff01;”&#xff0c;后来想了想&#xff0c;毕竟公众号里面还有那么多不同身份的粉丝&a…

算法面试,如何在100 亿URL中判断某个URL是否存在

转载自 算法面试&#xff0c;如何在100 亿URL中判断某个URL是否存在 如果面试官问你&#xff0c;一个网站有 100 亿 url 存在一个黑名单中&#xff0c;每条 url 平均 64 字节。问这个黑名单要怎么存&#xff1f;若此时随便输入一个 url&#xff0c;如何判断该 url 是否在这个…

链表 题

文章目录找出链表中类中点的位置判断该链表是否为回文结构将单向链表按某值划分成左边小、中间相等、右边大的形式给定一个有next指针和rand指针的Node 组成的无环单链表头节点&#xff0c;实现一个函数完成链表的复制&#xff0c;返回新链表的头节点给定两个可能有环也可能无环…

.NET Core 2.0迁移技巧之web.config配置文件

大家都知道.NET Core现在不再支持原来的web.config配置文件了&#xff0c;取而代之的是json或xml配置文件。官方推荐的项目配置方式是使用appsettings.json配置文件&#xff0c;这对现有一些重度使用web.cofig配置的项目迁移可能是不可接受的。 但是好消息是&#xff0c;我们是…