叮~ 学习总结

本文介绍了求解最大公约数的算法,使用了辗转相除法,同时探讨了快速幂运算。接着讲解了归并排序的原理及其实现,包括时间复杂度和空间复杂度分析。此外,还提到了冒泡排序和插入排序的基本思想和代码实现。文章以算法为核心,深入浅出地阐述了这些基础排序和计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习总结

求最大公约数

给出两个正整数a, b A,B,求它们的最大公约数。(1 <= a, b <= 1e9)

链接:问题 B: 最大公约数 - OJ (jsuacm.cn)

代码实现

int a,b,c,t;
scanf("%d%d",&a,&a);
    if(a>b)  //将相对较大的放在b,相对较小的放在a
    {
        t=a;
        a=b;
        b=t;
    }
    c=b%a;
    while(c) //如果c不等0的时候,一直循环
    {
        b=a;  //将较小的与相除的余数相除
        a=c;
        c=b%a;
    }
    printf("%d",a);

快速幂 

最大连续子段和

二分法

大数加法

大数减法

大数乘法

大数除法

栈和队列

链表

归并排序

今天认真的把归并看了之后才知道什么是痛苦面具,冒泡,选排简直太垃圾了(后来补的)

那我们直接进入正题吧:

特性:

时间复杂度:O(NlogN);

空间复杂度:O(logN);

是否稳定:是;

应用场景:数据量大且需要稳定时(常考类型:小和问题,逆序对问题)

基本思路:

将整个数列不断对半分开,并用新数组记下分开过后的数,直至分成一个数结束;

再由一个数起返回到初始数组,期间返回的每个过程种不断排序,到最后一次返回时,那么整个数列都是有序的

图文解释:

首先有10个数

 把他们对半拆开

再进行拆分(现只对左半部分进行解释),在拆分成一个数的时候就不能就行拆分了

拆分完之后就进行排序返回,一个数的时候就直接是本身

括号里面是在没有排序之前应该放的值 

之后右边的也是如此

代码实现:

#include <stdio.h>

void process(int* a,int L,int R){
    if(L == R) /*当左边的下标值等于右边的下标值时,就结束递归
                顾名思义就是分到只一个数时就结束递归*/
       return;
    int mid = L+((R-L)/2);    //计算中点
    process(a,L,mid);        //分开之后左边的数组
    process(a,mid+1,R);      //分开之后右边的数组
    merge_sort(a,L,mid,R);    //进行排序
}

void merge_sort(int* a,int L,int mid,int R){
    int arr[R-L+1];   //开一个新数组来存每个块,因为数组下标从0开始,所以要加一

    int i = L;  //左边数组起始下标
    int j = mid+1; //右边数组起始下标
    int k = 0;  //一块数组的起始下标
    while(i<=mid && j<=R){         //对满足条件的数进行排序
       arr[k++] = (a[i] < a[j]) ? a[i++] : a[j++];
    }

    while(i<=mid){       //将左边对已经剩下已经排好的数直接放在块数组里面
        arr[k++] = a[i++];
    }

    while(j<=R){        //将右边对已经剩下已经排好的数直接放在块数组里面
        arr[k++] = a[j++];
    }

    for(k=L;k<=R;k++){     //将排好序的块数组放在原初数组里面
        a[k] = arr[k-L];
    }
}

int main(){
    int n;
    printf("数组长度:");
    scanf("%d",&n);
    int a[n];
    printf("请输入一组数:");
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    process(a,0,n-1);
    
    for(int i=0;i<n;i++){
        printf("%d ",a[i]);
    }

    printf("\n");
}


我爱归并,归并爱我;

冒泡排序

冒泡排序是最基础的的排序方法,就像泡泡一样将一个一个数从大到小(从小到大)往后移动

 

(来自@烟雨倾城ゝ的动态图) 

原理 

第一个for循环一共分为n-1趟,第二个循环分为n-i-1次交换

第一趟,先比较一个数和第二个数,将较大的数放在后面,然后再比较第二个数和第三个数,再将较大的数放在后面,这样算下来,就会将这一躺中最大的数放在了最后面

第二趟,因为 第一躺将最大的数放在了最后面,也就是说后面的都已经是有序的了,所以交换穿次数就减少一次,然后再进行第一躺的操作,也就会将这一趟中最大的数放在了最后面

依次循环......

代码实现

  

#include<stdio.h>
int main()
{
   int i,j,t,n; //n是一共有多少个数
   scanf("%d",&n);
   int x[n];
   for(i=0;i<n;i++)scanf("%d",&x[i]);
   for(i=0;i<n-1;i++) //趟数
   {
       for(j=0;j<n-1-i;j++) //交换次数
       {
           if(x[j]>x[j+1]||x[j]==x[j+1]) //如果前面的一个数大于后面的数,就相互交换位置
           {
               t=x[j];
               x[j]=x[j+1];
               x[j+1]=t;
           }
       }
   }
   for(i=0;i<n;i++)printf("%d",x[i]);
    return 0;
}

插入排序

插入排序就是将打乱顺序的数把它放在最前面,然后再依次与有序的数列中的数进行比较,如果有个数小于它就将它放在那个数的前面

注意:应给数组第一个赋值为0,用来存数

图表示例:

给出一串数字,如:5 7 8 2 4 6

那么定义的数组就是本身的数列长度加上一个1

 先找打乱升序的数字——2,将他存在0处

然后再把这个数有序的数列依次往前面比较,再比较的过程的过程中,值不断后移动,最后找到比它小的数的前一个位置进行赋值

 

 依次循环...... 

代码实现:

#include<stdio.h>
int main()
{
    int k,n,i,j,a[100001]={0};
    scanf("%d",&k);
        scanf("%d",&n);
        //输入一个数列存进数组
        for(i=1;i<n+1;i++)scanf("%d",&a[i]); //从1开始因为第一个位置是来存数字的 
        for(i=2;i<n+1;i++) //从2开始是因为俩个数进行比较
        {
            if(a[i]<a[i-1])  //寻找打乱顺序的那个数
            {
                a[0]=a[i];   //将打乱顺序的那个数赋给0处
                //将打乱顺序的数进行比较,当找到比它小的数结束循环,将数插进那个数的前面
                for(j=i-1;a[0]<a[j];j--)  
                {
                    a[j+1]=a[j];
                }
                a[j+1]=a[0];
            }
        }
        for(i=1;i<n+1;i++)printf("%d ",a[i]);
    return 0;
}

枚举算法

枚举算法就是将所有可能出现的答案列举下来,然后再将你需要的留下,不需要的舍去

枚举最关键的将判断条件找齐,不能遗漏任何特殊的解

经典例题:问题 E: 智将点兵 - OJ (jsuacm.cn)

 

 代码实现:

#include<stdio.h>
int main()
{
    int a,b,c,d=0,s;
    scanf("%d%d%d",&a,&b,&c);
    for(s=10;s<101;s++) //将s可能出现的情况都列出来,如果满足条件就输出
    {
        if(s%3==a&&s%5==b&&s%7==c) //注意判断条件是否完整
        {
            printf("%d",s);
            d=1;
        }
    }
    if(d=0)printf("No answer");
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值