【AcWing】基础算法听课笔记


【基础算法】

[排序]

快速排序模板

快速排序是十分常用的高效率的算法。
其思想是:先选一个“标尺”,

用它把整个队列过一遍筛子,

以保证:其左边的元素都不大于它,其右边的元素都不小于它。
这样,排序问题就被分割为两个子区间。

再分别对子区间排序就可以了。

伪代码
void quick_sort(操作的数组,值的范围l,r)
{
   
    判断边界,给出递归出口  
    确定一个数x,确定指针i,j
    while(i<j)
    {
   
        若满足条件,指针向中间移动
        交换两指针所指向的数
    }
    中间数两端递归进行
}

//快速排序模板
#include<iostream>

using namespace std;

const int N=1e6+10;

int n;
int q[N];

void quick_sort(int q[],int l,int r)
{
   
    if(l>=r) return;
    int x=q[l],i=l-1,j=r+1;
    while(i<j)
    {
   
        do i++;while(q[i]<x);
        do j--;while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}

int main()
{
   
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);

    quick_sort(q,0,n-1);
    
    for(int i=0;i<n;i++) printf("%d",q[i]);

    return 0;
}

1while循环里面两个do while+一个一个判断 
2、尾递归

复杂度分析
平均时间复杂度:O(NlogN)
最佳时间复杂度:O(NlogN)
最差时间复杂度:O(N^2)

快速排序模板题

在这里插入图片描述

归并排序模板

思路:
 递归法
① 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
② 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
③ 重复步骤②,直到所有元素排序完毕
#include<iostream>

using namespace std;

const int N=1e6+10;

int n;
int q[N],tmp[N];

void merge_sort(int q[],int l,int r)
{
   
    if(l>=r) return;

    int mid=l+r>>1;

    merge_sort(q,l,mid),merge_sort(q,mid+1,r);//排序的过程

    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];   //放回原数组
}

int main()
{
   
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&q[i]);

    merge_sort(q,0,n-1);

    for(int i=0;i<n;i++) printf("%d ",q[i]);

    return 0;
}

1while循环里面一个判断 
2、头递归

复杂度分析:
平均时间复杂度:O(nlogn)
最佳时间复杂度:O(n)
最差时间复杂度:O(nlogn)
空间复杂度:O(n)
排序方式:In-place
稳定性:稳定

归并排序模板题

归并排序是用分治思想,分治模式在每一层递归上有三个步骤:

分解(Divide):将n个元素分成个含n/2个元素的子序列。
解决(Conquer):用合并排序法对两个子序列递归的排序。
合并(Combine):合并两个已排序的子序列已得到排序结果。
在这里插入图片描述
在这里插入图片描述

冒泡排序模板


#include <iostream>

using namespace std;

void bubble_sort(int arr[], int len)  
{
     
    int i, j;  
    for (i = 0; i < len - 1; i++)  
        for (j = 0; j < len - i-1; j++)  
            if (arr[j]>arr[j+1])  
                swap(arr[j],arr[j+1]);  
}

int main()
{
   
    int a[10] = {
   10, 9, 8, 7, 6, 5, 4, 3, 2, 1};

    for (int i = 0; i < 9; i ++// 十个数,只要排齐九个数另外一个数的位置自然也就确定了
        for (int j = 0; j < 9 - i; j ++) // 每排好一个数需要交换的次数就少一次,减一是因为交换一次变动的是两个数的位置。比如3 2 1 这三个数升序排列只需要交换两次就够。
            if (a[j] > a[j + 1]) 
                swap(a[j], a[j + 1]);
    
    for (int i = 0; i < 10; i ++) cout << a[i] << ' ';

    cout << endl;
    return 0;
}

二分模板

整数二分

//区间[l,r]被划分成[l,mid]和[mid+1,r]时使用:
int bsearch_1(int l,int r)
{
   
    while(l<r)
    {
   
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    return 1;
}
//区间[l,r]被划分成[l,mid-1]和[mid,r]时使用:
int bsearch_2(int l,int r)
{
   
    while(l<r)
    {
   
        int mid=l+r+1>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    return 1;
}

while循环里面一个判断
以 1 2 3 3 9为例,假如你想找到3的位置
二分模板1得到的3的位置编号为2,因为模板1是让尾巴取到中间值,再配合向下取整。
二分模板2得到的3的位置编号为3,因为模板三是让头取到中间值,再配合向上取整。
写的时候可以通过3 3 这种特殊的例子来想。


#include<iostream>

using 
  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值