快速排序算法备考

news2025/2/25 17:18:59

image.png

image.png

快排模板

快速排序(快排) (C语言实现)_c语言快速排序_Brant_zero2022的博客-CSDN博客
快排使用递归来实现
关键思想:划分


//划分
int partion(int A[],int L,int R){
      int mid=A[L];
	while(L<R){
	//每一次划分:左边元素<枢轴元素<右边元素
	//R往前找,直到找到一个比mid小的元素,然后把A[R]放在A[L]的位置
       while(A[R]>=mid && L<R){
           R--;
       }
        A[L]=A[R];
		while(A[R]<=mid && L<R){
           L++;
       }
    	A[R]=A[L];
    }
    //存放枢轴元素
     A[L]=mid;
    return L;
}

//快排
void quickSort(int A[],int L,int R){
	if(L>=R) return;//递归终止
    int M=partion(A,L,R);//返回中轴元素的下标
    //对中轴元素两边分别排序
    quickSort(A,L,M-1);
    quickSort(A,M+1,R);

}



快排的划分思想

image.png

快排划分思想的算法题

使用划分函数找到数组中第k小的元素

  • 数组中第k小的元素,说明这个元素的左边有k-1个元素比它小,利用快排的划分思想,我们只需要让划分函数返回k-1,就可以找到第k小元素。
  • 如果第一次划分后,返回下标为k-1,那么,我们就找到了这个元素
  • 如果返回的下标>k-1,说明接下来要在[L,M-1]进行划分
  • 如果返回的下标<k-1,说明接下来要在右边进行划分

int partion(int A[],int L,int R){
	int mid=A[L];
	while(L<R){	
        while(A[R]>=mid && L<R) R--;
        A[L]=A[R];
        while(A[L]<=mid && L<R) L++
            A[R]=A[L];
    }
    A[L]=mid;

}
//非递归实现
int min_k(int A[],int n,int k){
    int L=0,R=n-1;
	int M=0;
    while(1){
    M=partion(A,L,R);
 	if(M==k-1)  break;//说明找到了
    else if(M<k-1){
    	//在右边进行划分
       L=M+1;
    }else{
        //在左边进行划分
    	R=M-1;
    }

    }
   
	return A[K-1]

}

//递归实现
int min_k(int A[],int L,int R){
	int M=partion(A,L,R);
    if(M==k-1)  return A[M];//说明找到了
    else if(M<k-1){
    	//在右边进行划分
        min_k(A,M+1,R);
    }else{
    	min_k(A,L,M-1);

    }


}


分析非递归的复杂度
image.png
image.png

王道课后习题:在数组中找到第k小的元素

image.png
第k小,说明左边有k-1个元素比它小,利用快排的划分思想,只要返回下标为k即可

利用划分思想
//返回划分后的中轴元素的下标
int partion(int L,int left,int right){
	int mid=L[left];
    while(left<right){
    	while(L[right]>=mid && left<right) right--;
        L[left]=L[right];
        while(L[left]<=mid && left<=right) left++;
        L[right]=L[left];
    }
    L[left]=mid;
	return left;

}

int min_k(int L[],int n,int k){
    int left=1,right=n,M=0;
    while(1){
	  M=partion(L,left,right);
      if(M==k) break;
        else if(M<k)  left=M+1;//要在右边进行划分
    	else right=M-1;//左边划分
    }
	return L[k];



}

快排算法题实战应用

2011年42题

image.png

方法一双指针(我自己第一遍就想到的思路)

  1. 使用双指针,i指向序列S1元素,j指向S2序列元素,cnt用来记录已经比较的次数。比较s1,s2所指元素大小,如果S1所指元素大,则j向后移动,然后cnt++,如果S2所指元素大,则i向后移动,cnt++,当cnt==L/2时,此时,s1,s2所指元素大的那个就是中位数
  2. 代码

int find(int s1[],int s2[],int n){
	int i=j=cnt=0;
    for(cnt=0;cnt<n/2;cnt++;){
    	if(s1[i]<s2[j]){
            i++;
        }
        else{
           j++; 
        } 
    }
    //接下来比较s1,s2所指元素大小
    if(s1[i]>s2[j]){
        return s1[i];
    }else{
        return s2[j];
    }


}



时间复杂度:o(n)
空间复杂度:o(1)

方法二利用快排解决问题

把两个数组合并成一个大数组,然后用快排,下标L/2的元素就是中位数
image.png


//快排划分
int partion(int a[].int L,int R){
	int mid=a[L];
	while(L<R){
   	 while(a[R]>=mid&& L<R) R--;
    	a[L]=a[R];
    while(a[L]>=mid && L<R) L++;
        a[R]=a[L];
        a[L]=mid;
        return L;


}
//快排
    void qSort(int a[],int L,int R){
    	if(L<=R) return;
        int M=partion(a,L,R);
        qSort(a,L,M-1);
        qSort(a,M+1,R);
    }

    void find(int s1[],int s2[],int n){
    	int a[2*n];
        int i,j=0;
        //合并成一个数组
        for( i=0;i<n;i++)
            c[j++]=s1[i];
        }
    	for( i=n;i<2*n;j++){
    		c[j++]=s2[i];
    	}
    //排序
    qSort(a,0,2*n-1);
    return (0+2*n-1)/2;



    }



2013年41题

方法一利用哈希表(第一遍所想)

1.cnt数组记录元素大小0~n-1出现的次数,出现次数大于n/2的元素就是主元素
2.代码

void mainElement(int a[],int n){
	int cnt[n]={0};
    //元素值为i就存放在cnt数组的下标为i的位置,并且cnt对应位置元素值+1
    for(int i=0;i<n;i++){
    	cnt[a[i]]++;
    }
	//扫描cnt数组
    for(int i=0;i<n;i++){
    	if(cnt[i]>n/2) court<<i<<endl;
    }
    court<<"不存在主元素"<<endl;

}
3.时间复杂度:o(n)
    空间复杂度o(n)

方法二快排

主元素的元素数量超过数组长度的一半,如果数组有序,并且存在主元素,那么主元素一定在数组的中间位置
image.png

①无序--->有序  快排
②找n/2位置的元素
③从n/2往左、往右统计个数,然后判断存不存在

image.png

2018年41题

image.png
54

方法一哈希表

cnt数组用来记录元素i是否出现在数组中,cnt记录1n,如果元素i位于1n,则对应cnt数组相应位置+1


int fun(int a[],int n){
	int cnt[n+1];
    for(int i=0;i<n;i++){
        if(a[i]>=1 && a[i]<=n) {
        	cnt[a[i]]++;
        }
    }

//遍历cnt数组,如果cnt[i]==0,说明就是未出现的最小正整数
    for(int i=1;i<n;i++){
    	if(cnt[i]==0) return i;

    }
    //说明1~n都存在
    return n+1;

    
}

时间复杂度  O(n)
    空间复杂度  O(n)



image.png

方法二快排

image.png

2016年43题(本质是把乱序数组排成有序)

image.png

方法一利用快排

思路:想办法让右边元素大,左边元素小,而且尽量要把数组尽量平分,想到快排的划分思想,为了满足上述条件,右半部分的元素不能比左边元素个数少。
左边:0~n/2-1
右边:n/2~n-1

  1. 把数组A排成递增有序数列,排序后集合A1为[0,n/2-1],集合A2为[n/2n-1]

    此时[S1-S2]最大,[n1-n2]最小
    2.代码

①无序数组拍成有序数组
②说明A1,A2所在区间范围

 
//划分
int partion(int A[],int L,int R){
      int mid=A[L];
	while(L<R){
	//每一次划分:左边元素<枢轴元素<右边元素
	//R往前找,直到找到一个比mid小的元素,然后把A[R]放在A[L]的位置
       while(A[R]>=mid && L<R){
           R--;
       }
        A[L]=A[R];
		while(A[R]<=mid && L<R){
           L++;
       }
    	A[R]=A[L];
    }
    //存放枢轴元素
     A[L]=mid;
    return L;
}





//快排
void quickSort(int A[],int L,int R){
	if(L>=R) return;//递归终止
    int M=partion(A,0,n-1);//返回中轴元素的下标
    //对中轴元素两边分别排序
    quickSort(A,L,M-1);
    quickSort(A,M+1,R);

}










  1. 时间复杂度

    空间复杂度

image.png

方法二利用划分的思想(最优解)

我们知道快排在进行一次划分后,该元素的左边元素都比它小,右边都比它大。我们这道题目本质是把元素大的放右边,元素小的放左边,并没有要求按照 递增进行排序。其实,我们只要找到数组中第n/2小的元素。只要这个元素的位置确定了,那么它左边元素都比它小,右边都比它大。

//划分
int partion(int A[],int L,int R){
      int mid=A[L];
	while(L<R){
	//每一次划分:左边元素<枢轴元素<右边元素
	//R往前找,直到找到一个比mid小的元素,然后把A[R]放在A[L]的位置
       while(A[R]>=mid && L<R){
           R--;
       }
        A[L]=A[R];
		while(A[R]<=mid && L<R){
           L++;
       }
    	A[R]=A[L];
    }
    //存放枢轴元素
     A[L]=mid;
    return L;
}
//
void fun(int A[],int n){
	int M=0;
    int k=n/2;
    int L=0,R=n-1;
    while(1){
	M=partion(A,L,R);
	if(M==k-1) break;
        else if(M<k-1) L=M+1;
    	else R=M-1
    }
	//跳出循环说明已经找到第n/2小的元素

}

image.png

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

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

相关文章

ROS for LabVIEW:实现LabVIEW与ROS的无缝集成

ROS for LabVIEW是由Tufts大学开发的一套VI集合&#xff0c;旨在实现LabVIEW与ROS&#xff08;Robot Operating System&#xff09;的无缝集成。ROS是一个灵活的机器人软件框架&#xff0c;而LabVIEW则是一种强大的图形化编程工具。这个工具包的推出使得LabVIEW用户能够直接与R…

Neo4j安装部署及python连接neo4j操作

Neo4j安装部署及python连接neo4j操作 Neo4j安装和环境配置 安装依赖库&#xff1a; sudo apt-get install wget curl nano software-properties-common dirmngr apt-transport-https gnupg gnupg2 ca-certificates lsb-release ubuntu-keyring unzip -y 增加Neo4 GPG key&…

短视频真人配音:成都科成博通文化传媒公司

短视频真人配音&#xff1a;情感传递的新维度 随着数字化媒体的飞速发展&#xff0c;短视频已经成为人们日常生活中不可或缺的一部分。而在这个视觉盛宴的时代&#xff0c;真人配音的加入为短视频注入了新的活力&#xff0c;不仅丰富了内容形式&#xff0c;更使得情感传递达到…

Java面试八股之Synchronized锁升级的原理

Synchronized锁升级的原理 Synchronized锁升级是Java为了提高并发性能而引入的一项优化措施&#xff0c;这一机制主要发生在JDK 1.6及之后的版本中。Synchronized锁升级旨在减少锁带来的性能开销&#xff0c;通过从低开销的锁逐步升级到高开销的锁&#xff0c;以适应不同的竞争…

【吊打面试官系列】Java高并发篇 - 线程的调度策略?

大家好&#xff0c;我是锋哥。今天分享关于 【线程的调度策略?】面试题&#xff0c;希望对大家有帮助&#xff1b; 线程的调度策略? 线程调度器选择优先级最高的线程运行&#xff0c;但是&#xff0c;如果发生以下情况&#xff0c;就会终止线程的运行&#xff1a; 1、线程体…

I.MX6ULL的蜂鸣器实验-GPIO输入实验

系列文章目录 驱动开发中引入私有数据的原因 I.MX6ULL的蜂鸣器实验-GPIO输入实验 系列文章目录一、前言二、按键输入简介三、硬件原理四、程序编写4.1主要编写内容4.2程序编写前提工作4.3编写gpio驱动模块4.4编写按键KEY驱动模块 五、编译下载验证5.1 编写 Makefile 和链接脚本…

C++ 头文件优化

C 是一种灵活的语言&#xff0c;所以需要一种积极的方法来分析和减少编译时依赖。一种常见的达到这个目的的方法是&#xff0c;将依赖从头文件里转移到源代码文件里。实现这个目的的方法叫做提前声明。 简而言之&#xff0c;这些声明告诉编译器某个函数接受和返回哪些参数&…

用友NC linkVoucher SQL注入漏洞复现

0x01 产品简介 用友NC是由用友公司开发的一套面向大型企业和集团型企业的管理软件产品系列。这一系列产品基于全球最新的互联网技术、云计算技术和移动应用技术,旨在帮助企业创新管理模式、引领商业变革。 0x02 漏洞概述 用友NC /portal/pt/yercommon/linkVoucher 接口存在…

YOLOv8+PyQt5鸟类检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

资源包含可视化的鸟类检测系统&#xff0c;基于最新的YOLOv8训练的鸟类检测模型&#xff0c;和基于PyQt5制作的可视化鸟类检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的各种鸟类&#xff0c;以及自动开启摄像头…

腾盾科创无人机亮相第二十四届新疆农机博览会引发观展热潮

5月25日&#xff0c;第二十四届新疆农业机械博览会、2024“一带一路”智慧农业大会&#xff08;以下简称新疆农机博览会&#xff09;在新疆国际会展中心开幕。展会现场多种农牧业的新装备、新技术集中亮相&#xff0c;其中首次在新疆农机博览会上亮相的腾盾科创无人机产品引发观…

视觉语言模型详解【VLM】

视觉语言模型&#xff08;Visual Language Models&#xff09;是可以同时从图像和文本中学习以处理许多任务的模型&#xff0c;从视觉问答到图像字幕。在这篇文章中&#xff0c;我们将介绍视觉语言模型的主要组成部分&#xff1a;概述&#xff0c;了解它们的工作原理&#xff0…

MySQL事务篇2:InnoDB引擎

InnoDB是MySQL的默认存储引擎&#xff0c;支持ACID事务、行级锁定和外键约束&#xff0c;通过多版本并发控制&#xff08;MVCC&#xff09;实现高并发性能。InnoDB使用聚簇索引存储数据&#xff0c;具备崩溃恢复能力&#xff0c;确保数据一致性和完整性。其主要特性包括数据和索…

谷粒商城实战(029 业务-订单支付模块-支付宝支付2)

Java项目《谷粒商城》架构师级Java项目实战&#xff0c;对标阿里P6-P7&#xff0c;全网最强 总时长 104:45:00 共408P 此文章包含第305p-第p310的内容 代码编写 前端代码 这里使用的是jsp 在这里引用之前配置的各种支付信息 在AlipayConfig.java里 这里是调用阿里巴巴写…

【onnx问题解决】关键词:found at least two devices、torch.onnx.export

关键词&#xff1a;Expected all tensors to be on the same device, but found at least two devices, cpu and cuda:0! 报错&#xff1a; [34m[1mONNX:[0m export failure ❌ 3.8s: Expected all tensors to be on the same device, but found at least two devices, cpu an…

【R语言】获取任意颜色的HTML 颜色代码、十六进制颜色代码、 RGB代码

网站来源&#xff1a; https://htmlcolorcodes.com/ 界面如下所示&#xff1a; 通过鼠标任意选择不同的颜色&#xff0c;就能获取该色的十六进制代码、RGB代码等。 除此之外&#xff0c;还提供了一些常用颜色的便捷选项,如下&#xff1a; 任意选择一种颜色&#xff0c;即可出…

Java开发快速入门

Java执行流程分析 .java文件 **(源文件)** ---javac编译--->.class文件 **(字节码文件)** ---java运行--->结果 运行的本质: .java文件称之为源文件 .class文件称之为字节码文件 什么是编译 javac Hello.java 1. 有了java源文件, 通过编译器将其编译成JVM可以识别的…

【吊打面试官系列】Java高并发篇 - AQS 支持几种同步方式 ?

大家好&#xff0c;我是锋哥。今天分享关于 【AQS 支持几种同步方式 &#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; AQS 支持几种同步方式 &#xff1f; 1、独占式 2、共享式 这样方便使用者实现不同类型的同步组件&#xff0c;独占式如 ReentrantLock&…

C语言动态顺序表结构的创建、初始化结构、尾插、尾删、头插、头删、指定位置插入、指定位置删除、找指定数值下标等的介绍

文章目录 前言一、 结构创建二、 初始化结构三、 打印动态顺序表四、 销毁动态顺序表五、 尾插六、尾删七、 头插八、 头删九、指定位置插入十、指定位置删除十一、找指定数值下标总结 前言 C语言动态顺序表结构的创建、初始化结构、尾插、尾删、头插、头删、指定位置插入、指…

Java 实验12 线程同步与通信

&#xff08;一&#xff09;实验目的 1、掌握JAVA中多线程的实现方法&#xff1b; 2、重点掌握多线程的同步与通信机制&#xff1b; 3、熟悉JAVA中有关多线程同步与通信的方法 &#xff1b; 4、能使用多线程机制解决实际应用中的线程同步与通信问题。 &#xff08;二&…

【社会信用体系1003】 企业违规新解:社会信用环境改善的实证分析!

今天给大家分享的是来自于国内顶级期刊金融研究2023年发表论文——《社会信用环境改善降低了企业违规吗&#xff1f;——来自“中国社会信用体系建设”的证据》所用到的重要数据集&#xff0c;该文章从企业层面探讨了社会信用系统建设对企业违规行为的影响&#xff0c;更精准地…