(归并排序 快排 堆)

文章目录

    • 归并排序
        • 递归方法实现
        • 非递归方法实现
        • 求数组的小和
        • 求数组的降序对个数
    • 快排
        • 荷兰国旗问题(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…

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;你才能在遇…

程序配置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;笔者将其代码压缩成如…

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

大家好&#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 是否在这个…

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

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

学会它,可以替你写100行 200行 300行……的代码

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。今天&#xff0c;给大家分享一个非常非常使用的小技巧&#xff0c;那就是&#xff1a;“在webstrom中创建一个简单的vue模板”&#xff0c;根据这个方法&#xff0c;你可以任意的创建html模…

Java中随机数的原理,以及使用时的注意点

转载自 Java中随机数的原理&#xff0c;以及使用时的注意点 1 前言 一提到 Java 中的随机数&#xff0c;很多人就会想到 Random&#xff0c;当出现生成随机数这样需求时&#xff0c;大多数人都会选择使用 Random 来生成随机数。Random 类是线程安全的&#xff0c;但其内部使…

MySql 使用 EF Core 2.0 CodeFirst、DbFirst、数据库迁移(Migration)介绍及示例

dotnet core 2.0 发布已经好几天了&#xff0c;期间也把原来 dotnet core 1.1 的 MVC 项目升级到了 2.0&#xff0c;升级过程还是比较顺利的&#xff0c;变动也不是太多。升级的过程中也少不了 Entity Framwork Core 的升级&#xff0c;在这篇文章中主要介绍下 MySql 数据库使用…

下午带着几个同学打了两节课的牌~

大家好&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。大赛的项目目前正在火热进行中&#xff0c;靳天宇小组做的是扑克牌的游戏&#xff0c;除了要做大家耳熟能详的“斗地主”之外&#xff0c;另外在我的建议下准备再加两种玩法&#xff0c;一…

jzoj2137-(GDKOI2004)城市统计【二维前缀和,bfs】

正题 大意 有n*n的矩阵&#xff0c;有居民区有商业区&#xff0c;每个居民区曼哈顿距离最近的商业区的曼哈顿距离就是那个居民区离商业区的距离。每个格子统计一下以它为中心的2∗r12∗r12∗r12∗r1的矩阵内所有居民区离商业区的距离的和。 解题思路 先bfs计算所有居民离商业…

Razor Page–Asp.Net Core 2.0新功能 Razor Page介绍

Razor Page介绍 前言 上周期待已久的Asp.Net Core 2.0提前发布了&#xff0c;一下子Net圈热闹了起来&#xff0c;2.0带来了很多新的特性和新的功能&#xff0c;其中Razor Page引起我的关注&#xff0c;作为web程序员来说&#xff0c;Asp.Net下的任何web框架都会去特别关注&…