基础算法一

排序: 快排 归并排序
二分: 整数 浮点数

快速排序
1.主要思想---->代码
2.每个题的模板写出来—> 默写
3.题目------> 有对应解决方案

以上3个步骤反复进行

快速排序----->分治

1.确定分界点q[l],q[(l+r)/2],q[r] 随机
***2.划分区间(调整区间) 两部分

|---------------------------|--------------------------|
<=x >=x

3.递归处理左右两段

划分区间解法1
1.开两个数组: a[], b[]
2.q[l~~r]:
q[i]<=x; x–>a[]
q[i]>=x; x–>b[]
3.a[]–>q[], b[]—>q[];
划分区间解法2
3 1 2 3 5 x = 3
选定一个哨兵值,哨兵值两边所有元素与哨兵值比较,左边的进行比较如果大於则交换,右边的进行比较,若小於则交换。
快速排序模板:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int n;
int a[N];
void quick_sort(int a[],int l,int r){
	if(l>=r) return;
	int i=l-1,j=r+1;
	int x=a[l];
	while(i<j){
do	i++;while(a[i]<x);  //指针1 
do	j--;while(a[j]>x);//指针2
	if(i<j) swap(a[i],a[j]);
	}
	quick_sort(a,l,j);
		quick_sort(a,j+1,r);
	
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	scanf("%d",&a[i]);
	quick_sort(a,0,n-1);
	for(int i=0;i<n;i++)
	printf("%d ",a[i]);
	
	return 0;
}

归并排序
1.主要思想---->代码
2.每个题的模板写出来—> 默写
3.题目------> 有对应解决方案

以上3个步骤反复进行

归并排序----->分治

1.找分界点---->确定分界点mid==(l+r)/2
2.递归排序左边和右边
***3.归并(合二为一)
双指针算法:
1 3 5 7 9 指针1
2 4 5 8 10 指针2
^
双路归并,合二为一(1and2 =1,指针1++,…)
res: 1 2 3 4 5 5 7 8 9 10
稳定不稳定没什么nuan 用。。。!
n
n/2 n/2
n/4 n/4 n/4 n/4
.
.
.
.
最后是排好序的1/n份数值。
归并排序模版:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e6+10;
int n;
int a[N],tmp[N];
void merge_sort(int a[],int l,int r){
	if(l>=r) return;
	int mid=(l+r)>>1;
	merge_sort(a,l,mid),merge_sort(a,mid+1,r);
	int k=0,i=l,j=mid+1;
	while(i<mid&&j<=r)
	if(a[i]<=a[j]) tmp[k++]=a[i++];
	else tmp[k++]=a[j++];
	while(i<=mid) tmp[k++]=a[i++];
	while(j<=r) tmp[k++]=a[j++];
	
	for(i=l,j=0;i<=r;i++,j++) a[i]=tmp[j];
	
	
}
int main(){
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	scanf("%d",&a[i]);
	merge_sort(a,0,n-1);
	for(int i=0;i<n;i++)
	printf("%d ",a[i]);
	
	return 0;
}

这3种排序最快胡是归并,然后是快排,最后是sort。

二分(整数和实数)
整数二分1;
前部分 后部分
|-----------mid---------------|------------------------------|
l mid r
1.找中间值 mid=(l+r)/2;
if(check(mdi)) true 时,mid在前部分(进行边界分界),false时在后部分(进行边界分界)。
二分的本质: 只要拥有单调性,一定可以二分,可以二分的但不一定单调。所以整数二分的本质是 :边界。
整数二分算法1(mid在左部分):
区间[l,r]被划分为[l,mid]和[mid+1,r]时使用。

int besearch_1(int l,int r){
while(l<r){
int mid=l+r>>1;
if(check((mid)) r=mid;//check判断mid是否满足性质
else l=mid+1;

整数二分算法1(mid在右部分):
整数二分2;
前部分 后部分
|--------------------------|---------------mid---------------|
l mid r
1.找中间值 mid=(l+r)/2;
if(check(mdi)) true 时,mid在后部分(进行边界分界),false时在前部分(进行边界分界)。
区间[l,r]被划分为[l,mid]和[mid+1,r]时使用。

int besearch_1(int l,int r){
while(l<r){
int mid=(l+r+1)>>1;//+1可以防止死循环 下一语句判断为true时不会出错。
if(check((mid)) l=mid;//check判断mid是否满足性质
else r=mid-1;

针对二分问题: 边界写好–>写二分–>判断(答案在左右的哪部分)是哪一种,前部分l+r,后部分l+r+1的问题,而扽不需要考虑是否无解,但是可以得出来元问题是否无解。

浮点数二分:
不需要处理边界问题,所以比较容易。
举例子:

#include<iostream>
using namespace std;
int main(){
double x;
cin>>x;
double l=0,r=x;
while(r-l>1e-8) {//区间大于10的-8次方,题目让保留5位小数,就多2,就不会有误差问题,这是经验问题
double mid=(l+r)/2;
if(mid*mid>=x) r=mid;//不需要处理边界,没+1和-1
else l=mid;
}
printf("%lf\n",l);
return 0;
}

question:785,786,787,788,789,790

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章