进击高手【第一期】(排序)

本文详细介绍了快速排序和归并排序的图解、模板代码及应用实例,包括寻找第k小数、逆序对数、最大次大元素等问题。同时探讨了二分查找的运用,如查找下界、上界和最接近的元素,并通过间接二分解决特定问题。通过这些案例,深入理解分治思想在排序和查找算法中的应用。
摘要由CSDN通过智能技术生成

快速排序

图解

先找到左哨兵作为基准数,右哨兵移动到比基准数小的数,左哨兵再移动到比右哨兵大的数。
在这里插入图片描述

交换两个数

在这里插入图片描述

重复上述过程,直到两哨兵相遇

在这里插入图片描述

相遇后将基准数与本数交换
在这里插入图片描述

这样就完成了第一轮交换,可以发现基准数已归位且在基准数左侧的数都比基准数小,右侧的数都比基准数大。只需分左右依次递归即可。

递归树
在这里插入图片描述

模板代码

void qsort(int l,int r){
   
	if(l>=r) return;
	int sol=a[l];
	int i=l,j=r;
	while(i!=j){
   
		while(a[j]>=sol&&i<j)j--;
		while(a[i]<=sol&&i<j) i++;
		if(i<j) swap(a[i],a[j]);
	}
	swap(a[l],a[i]);
	qsort(l,i-1);
	qsort(i+1,r);
}

例子

  1. 第k小数1

题目描述
对于给定的n个元素的无序数组,要求从中找出第k小的元素。

输入格式
第一行是总数n(1<n<100000)和k,第二行是n个待比较元素。

输出格式
第k小的数在数组中的位置(若有多个,请输出最左边的元素位置)。

样例输入

5 3
25 9 90 57 3

样例输出

1

只需将模板改为

void qsort(int l,int r){
   
	int sol=a[l];
	int i=l,j=r;
	while(i!=j){
   
		while(a[j]>=sol&&i<j)j--;
		while(a[i]<=sol&&i<j) i++;
		if(i<j) swap(a[i],a[j]);
	}
	swap(a[l],a[i]);
	if(k==i){
   
		p=a[i];
		return;
	}
	else if(k<i) qsort(l,i-1);
	else qsort(i+1,r);
}

因为我们只需第k小数,比k大或小不需要浪费时间去递归

  1. 第k小数2通上

题目描述
对于两个有序数组a[n]和 a[m] (1<n,m<100000),找出第k小的数。

输入格式
第一行三个整数n,m,k。
第二行是第一个有序数组的n个元素。
第三行是第二个有序数组的m个元素。

输出格式
第k小的数。

样例输入

6 7 6
786 3891 4258 4694 7130 7899
357 720 1292 2579 7889 9255 9611

样例输出

3891

只需将两组输入合并即可

归并排序

图解

第一步将原数组对半分,直到只剩下一个元素时停止。

在这里插入图片描述
第二步将分开的数组依次已小在前合并
请添加图片描述

模板代码

void merge(int head,int tail){
   
	int mid=(head+tail)/2;
	int s=head,e=mid+1,k=0;
	while(s<=mid&&e<=tail){
   
		if(a[s]>a[e]) temp[k++]=a[e++];
		else temp[k++]=a[s++];
	} 
	while(s<=mid) temp[k++]=a[s++];
	while(e<=tail) temp[k++]=a[e++];
	k=0;
	for(int i=head;i<=tail;i++) a[i]=temp[k++];
}
void m_sort(int head,int tail){
   
	int mid=(head+tail)/2;
	if(head<tail){
   
		m_sort(head,mid);
		m_sort(mid+1,tail);
		merge(head,tail);
	}
	return;
}

例子

  1. 求逆序对数
    请添加图片描述

只需在合的过程中,只要这个数比另一个数小,那么比这个数小的数一定也比另一个数小,所以答案加上mid-s+1。

  1. 查找最大和次大元素

题目描述

对于给定的含有n元素的无序序列,求这个序列中最大和次大的两个不同的元素,序列保证没有相同的数字。
例如:(2, 5, 1, 4, 6, 3),最大元素为6,次大元素为5。

输入格式
输入有两行
第一行一个正整数n,表示序列中数字的数量
第二行有n个空格分开的整数,表示这个序列中的数字

输出格式
输出由两个空格隔开的数字,第一个表示最大值,第二个表示次大值

样例输入

6
2 5 1 4 6 3

样例输出

6 5

void f(int l,int r,int &max1,int &max2
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值