快速排序–分治(用数)
思想
1.确定分界点x:左边界/中间/右边界/随机
2.调整区间:<=x,(分界点不一定是x),>=x
3.递归处理左右两个区间
代码
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;//边界检查
int i = l , j = r , x = q[l ];//i
while (i < j)
{
while (q[i] < x) i++;
while (q[j] > x) j++;
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);//此时j在i左边,此时x不能选左边界,防止死循环
}
最好使用scanf,比cin快
选左边界,用右指针递归
选右边界,用左指针递归
归并排序–分治(数组mid)
思想
1.确定分界点:mid=(left+right)/2
2.递归排序左右两个分区
3.合二为一,将两个有序的数组合并为一个:双指针算法 O(n)
代码
int tmp[];//中间数组0
void merge_sort(int q[], int l, int r)
{
if (l >= r) return;//边界条件
int mid = l + r >> 1; //右移1位操作相当于除2
merge_sort(q, l, mid);//左递归
merge_sort(q, mid + 1, r);//右递归
//合并,空间O(n)
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}
稳定性:元素的相对位置在排序之后不变则稳定,否则不稳定
快排:不稳定,改进改为二元组排序<a[i],i> 平均O(nlogn)
归并:稳定 O(nlogn)
3.二分
3.1整数二分
注意边界问题,会造成死循环
有单调性的题目一定可以二分
可以二分的题目不一定具有单调性
思路
mid=l+r/2
模板
bool check(int x){}
//向下取整,区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用
int binsearch1(int l,int r)
{
while(l<r)
{
int mid=(l+r)/2;
if(check(mid)) r=mid;
else l=mid+1;
}
return l;
}
//向上取整,区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:
int binsearch2(int l,int r)
{
while(l<r);
{
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
return l;
}
l=mid mid=l+r+1>>1
二分的时候一定是有解的,一定可以将边界分出来
无解是因为题目
3.2 浮点数二分
没有边界问题,区间可以严格的对半分
模板