基礎算法一

排序: 快排 歸併排序
二分: 整數 浮點數

快速排序
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

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