学习总结
求最大公约数
给出两个正整数a, b A,B,求它们的最大公约数。(1 <= a, b <= 1e9)
代码实现
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;
}
枚举算法
枚举算法就是将所有可能出现的答案列举下来,然后再将你需要的留下,不需要的舍去
枚举最关键的将判断条件找齐,不能遗漏任何特殊的解
代码实现:
#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;
}