当前位置:网站首页>随机快排时间复杂度是N平方?
随机快排时间复杂度是N平方?
2022-08-09 12:00:00 【爱敲代码的Harrison】
数组分区—partition
给定一个数组arr,和一个整数num,请把小于等于num的数放在数组左边,大于num的数放在右边。
分析:设计一个<=区,该区域一开始在数组左侧,只用一个变量记录它的右边界,所以一开始<=区在下标为-1的位置,然后开始遍历数组(0,1,2…N-1)
遍历规则:
- i位置的数[i] <= num:把当前数和<=区的下一个数交换,然后<=区向右扩一个位置,当前数跳到下一个(i++)
- [i] > num:什么也不干,直接i++
题目升级
将数组分为三段,[< | = | >] ——经典的荷兰国旗问题,小于部分和大于部分可以无序。
分析
设计一个>区,往左扩,<区,往右扩,i位置从左往右遍历,必然会中三中逻辑:
- [i] == num:直接i++
- [i] < num:[i]与<区的下一个数(或者说右一个数)交换,然后<区右扩一个,i++
- [i] > num:[i]与>区的左一个数交换,然后>区左扩,i停在原地
- 什么时候停?i和>区的左边界撞上的时候
随机快排
- 快排1.0版本:以arr[R]做划分值,进行一次partition搞定一个数,然后左侧范围区递归,以左侧范围的arr[R]做划分值,右侧同理,周而复始
- 快排2.0版本:与1.0一样,但是一次能搞定等于arr[R]的一批数
- 快排3.0版本:随机选一个数(如[i]位置的数),将其与arr[R]交换之后,以arr[R]做划分值。就等同于随机选一个数拿它做划分值,剩下的所有过程跟快排2.0一样
随机快排时间复杂度分析
- 划分值越靠近中间,性能越好,越靠近两边,性能越差
- 随机选一个数进行划分的目的就是让好情况和坏情况都变成概率事件
- 把每一种情况都列出来,会有每种情况下的时间复杂度,但概率都是1/N
- 把每一种情况都考虑,时间复杂度就是这种概率模型下的长期期望
- 时间复杂度O(N*logN)和额外空间复杂度O(logN)都是这么来的
- 快排为什么要用递归运行,因为要记录每一个中点的位置或划分点的位置,递归空间就是每次记录划分值的空间,这是避免不掉的。
package com.harrison.java;
public class test {
// 在数组arr[L...R]上,以arr[R]做划分值
// 小于等于arr[R]的数放左侧(左侧的数可以无序)
// 大于arr[R]的数放右侧(右侧的数可以无序)
public 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++;
}
// L...lessEqual lessEqual+1...R-1 R
// L.............lessEqual+1 lessEqual+2...R
swap(arr, ++lessEqual, R);
return lessEqual;
}
// arr[L...R] 玩荷兰国旗问题的划分,以arr[R]做划分值
// <arr[R] | ==arr[R] | >arr[R]
public static int[] netherlandFlags(int[] arr,int L,int R) {
if(L>R) {
return 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, index++, ++less);
}else {
swap(arr, index, --more);
}
}
// L...less less+1...more-1 more...R-1 R
// L...less less+1..........more more+1...R
swap(arr, more, R);
return new int[] {
less+1,more};
}
public static void swap(int[] arr, int i, int j) {
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
//快排1.0
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;
}
int M=partition(arr, L, R);
process1(arr, L, M-1);
process1(arr, M+1, R);
}
//快排2.0
public static void quickSort2(int[] arr) {
if(arr==null || arr.length<2) {
return ;
}
process2(arr, 0, arr.length-1);
}
public static void process2(int[] arr,int L,int R) {
if (L >= R) {
return;
}
int[] equalArea=netherlandFlags(arr, L, R);
process2(arr, L, equalArea[0]-1);
process2(arr, equalArea[1]+1, R);
}
public static void quickSort3(int[] arr) {
if(arr==null || arr.length<2) {
return ;
}
process3(arr, 0, arr.length-1);
}
//快排3.0
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=netherlandFlags(arr, L, R);
process3(arr, L, equalArea[0]-1);
process3(arr, equalArea[1]+1, R);
}
public static int[] generateRandomArray(int maxSize, int maxValue) {
int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
for (int i = 0; i < arr.length; i++) {
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
}
return arr;
}
public static int[] copyArray(int[] arr) {
if (arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
public static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
return false;
}
if (arr1 == null && arr2 == null) {
return true;
}
if (arr1.length != arr2.length) {
return false;
}
for (int i = 0; i < arr1.length; i++) {
if (arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
public static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
int testTimes=1000000;
int maxValue=100;
int maxSize=100;
boolean succeed=true;
for(int i=0; i<testTimes; i++) {
int[] arr1=generateRandomArray(maxSize, maxValue);
int[] arr2=copyArray(arr1);
int[] arr3=copyArray(arr1);
quickSort1(arr1);
quickSort2(arr2);
quickSort3(arr3);
if(!isEqual(arr1, arr2) || !isEqual(arr2, arr3)) {
succeed=false;
printArray(arr1);
printArray(arr2);
printArray(arr3);
break;
}
}
System.out.println(succeed?"Nice":"Oops");
}
}
边栏推荐
猜你喜欢

ABAP 报表中如何以二进制方式上传本地文件试读版

内网穿透工具ngrok使用教程

Common gadgets of Shell (sort, uniq, tr, cut)

JD.com architects tidy up: what are the core technical knowledge points of jvm and performance tuning

web course design

箭头函数和普通函数的常见区别

【微服务~远程调用】整合RestTemplate、WebClient、Feign

ThreadLocal的简单理解

Programmer's Exclusive Romance - Use 3D Engine to Realize Fireworks in 5 Minutes

报告:想学AI的学生数量已涨200%,老师都不够用了
随机推荐
How should the acceptance criteria for R&D requirements be written?| Agile Practices
从零开始Blazor Server(9)--修改Layout
MySQL principle and optimization of Group By optimization techniques
软件测试——金融测试类面试题,看完直接去面试了
Win10 compiles the x264 library (there are also generated lib files)
JD.com architects tidy up: what are the core technical knowledge points of jvm and performance tuning
shell脚本------函数的格式,传参,变量,递归,数组
GPT-3组合DALL·E,60秒内搞定游戏设定和原型动画!网友看后:这游戏想玩
阿里高工带来的20022最新面试总结太香了
The grep command Shell regular expressions, the three musketeers
WPF implements a MessageBox message prompt box with a mask
告别手摇织布机的AI时代
MySQL 原理与优化,Group By 优化 技巧
HAproxy:负载均衡
Byte Qiu Zhao confused me on both sides, and asked me under what circumstances would the SYN message be discarded?
Common gadgets of Shell (sort, uniq, tr, cut)
GET请求和POST请求区别
【微服务~远程调用】整合RestTemplate、WebClient、Feign
《数字经济全景白皮书》银行业智能营销应用专题分析 发布
【重要】C语言进阶 -- 自定义类型:结构体、枚举、联合