【代码笔记】

这是一个拥有c++云课堂所有知识点的代码笔记

可以让一个不会的新手变成一个大佬的笔记

(持续更新)(持续更新)(持续更新)(重要事情说三遍)

目录

这是一个拥有c++云课堂所有知识点的代码笔记

可以让一个不会的新手变成一个大佬的笔记

(持续更新)(持续更新)(持续更新)(重要事情说三遍)

1级

第一课--头文件的调用

第二课--定义数组

第三课--运算符

 第四课--bool变量

第五课--if语句

第六课--复合语句

第七课--for语句

第八课--累加器

第九课--查找最值

第十课--嵌套循环

第十一课--数位分离

2级

第一课--定义数组

第二课--最大最小值查找

 第三课--数组元素的移动、插入、删除

第四课--选择排序

第五课-sort函数

第六课--输入输出函数

第七课--模拟算法

第八课--周期问题

第九课--简单递推

第十课--简单枚举

第十一课--下计计数

第十二课--求连续相同的一段数

3级 

第一课--回文数

第六课--字符串的定义,输出,输入与运用

4级

第九课--的语法知识

5级

6级

第十一课--二维前缀和

一、如何预处理

二、如何查询

第六课--动态数组

第九课--栈的运用

第十课--队列

双向队列


1级

第一课--头文件的调用

/*
陈袁鑫
2023.9.23
9.23做
*/
//调用头文件
#include <iostream>
using namespace std;
//代码主题
int main()
{
    //数字
    cout<<25<<endl;
    //算式
    cout<<10+130<<endl;
    //程序运行时,会自动计算得数并将得数输出,所以运行结果是94
    //输出字符或字符串
    cout<<"A"<<endl;
    cout<<"abcd"<<endl;
    //当输出项为一串用双引号引起的字符(称为字符串)时,则原样输出双引号中的内容。
    //两种结合
    //cout可以有一个输出项,也可以有多个输出项
    cout<<"A"<<" "<<"abcd"<<endl;
    //每一句话都以分号结尾
    return 0;           
}

第二课--定义数组

/*
陈袁鑫
2023.9.23
9.23做
*/

#include <iostream>
using namespace std;
int main()
{
    //数组的定义
    int n;//声明一个变量
    //赋值
    n=10;
    //可以在定义的时候赋值int n=10;
    //间接复制
    int m;
    m=n;
    //自己赋值
    n=n*1;
    n=n-1
    ....
    //加与减
    int x=2,y=2;
    x++;//x+1
    y--;//y-1
    //输入
    int n1;
    cin>>n1;
    cout<<n<<endl<<m<<endl<<<x;
    return 0;           
}

第三课--运算符

/*
陈袁鑫-C01L03
2023.9.24做
*/
#include <iostream>
using namespace std;
//运算符
int main()
{
    //运算符有:+,-,*,/,%
    int n;
    n=10;
    n*=2;
    //相当于10x2=20
    int m=5;
    m/=2;//int类型的只保留整数,除非用float(单精度) 或double(双精度)
    //注意:每一个运算符之后都要加一个=,不然会报错
    int k=10;
    k+=10;
    //与正常加法一样
    int n1=6;
    n1-=1;
    //与正常减法一样
    int a=10;
    a%=10;
    //代表a除10的余数
    cout<<"n*2的值是:"<<" "<<n<<endl;
    cout<<"m/2的值是:"<<" "<<m<<endl;
    cout<<"k+10的值是:"<<" "<<k<<endl;
    cout<<"n1-1的值是:"<<" "<<n1<<endl;
    cout<<"a%2的值是:"<<" "<<a<<endl;
    return 0;
}

 第四课--bool变量

/*
陈袁鑫-C01L04
2023.9.24做
*/
#include <iostream>
using namespace std;
//关系表达式
int main()
{
    if(2==3){
        //==相当于等于
        //2不等于3
        cout<<"true";
        //true表示✔
    }
    else{
        cout<<"false";
        //false表示❌
    }
    //上列代码表示判断2等不等于3
    //if是如果,else是否则
    /*
    if(变量1==或>或<或>=或变量2){
        是的条件
    }
    else{
        否则的条件
    }
    */
    bool f;
    //bool 布尔类型变量
    //布尔型的数据用来表示某个事情有且只有两种可能的结果: true 和 false 。
    //一般用 true 表示肯定意义的结果,也就是真的、成立的;
    //用 false 表示某种否定意义上的结果,也就是假的、不成立的。
    
    //&&表示并且
    //||表示或者
    
    return 0;
}

第五课--if语句

/*
陈袁鑫
2024.9.25
第五课嵌套if
*/
#include <iostream>
using namespace std;

int main()
{
    int n;
    n=10;
    //if语句格式:
    /*
    if(变量1>或==或<或>=或<=){
        如果是的条件
    }
    else{
    如果不是的条件
    }
    */
    //比如
    if(n>2){
        cout<<"是";
    }
    else{
        cout<<"不是";
    }
    //还可以嵌套
    if(n>=10){
        if(n>2){
            cout<<"是";
        }
        else{
            cout<<"不是";
        }
    }
    //切记,只有if才有else,否则会报错
    return 0;
} 

第六课--复合语句

/*
陈袁鑫
2024.9.25
第六课复合语句
*/
#include <iostream>
using namespace std;

int main()
{   
    //我们来看下面的代码
    int n=10,a=0,b=0,c=0;
    if(n>0)
    a+=2;
    b+=2
    c+=2;
    cout<<a<<" "<<b<<" "<<c<<endl;
    //运行上列代码,就会发现,当if语句后面有多个语句的时候
    //if语句识别不到后面的语句
    //这时,就要用一个大括号{},将代码包在里面,就可以运行多个语句了
    int m=10,d=0,e=0,f=0;
    if(m>0){
        d+=2;
        e+=2;
        f+=2;
    }
    cout<<d<<" "<<e<<" "<<f;
    return 0;
} 

第七课--for语句

/*
陈袁鑫
2024.9.25
第七课for语句
*/
#include <iostream>
using namespace std;

int main()
{   
    //如果要一下子输出多个代码的话,普通人只会用cout输出
    //但有些人却会用for循环来写
    //如下
    for(int i=1;i<=1000;i++){
        cout<<"YES";
    }
    cout<<"________________________";
    //for循环可以将括号里的代码执行上面小括号里填的数的次数
    /*
    for(变量类型,变量名=开始值;变量名<=结束值;变量名+=累加的次数){
        代码
    }
    */
    //还可以
    for(float i=0.5;i<=8.5;i+=0.5){
        cout<<"YES";
    }
    return 0;
} 

第八课--累加器

/*
陈袁鑫
2024.9.25
第八课累加器
*/
#include <iostream>
using namespace std;

int main()
{   
    //如果你要求出1+到1000是多少
    //那就不得不用累加器了
    //代码如下
    int s=0;
    for(int i=1;i<=1000;i++){
        s+=i;
    }
    cout<<"s的值是:"<<s<<"_____________";
    //正如你所见,累加器只是拿一个变量来加,+号在前面讲过
    //相当于一个数来加一个,累加器必须要搭配for来用,要么就加100甚至上千次
    //s的类型是什么,它加的数就是什么,比如s的类型是double,它就要+小数
    return 0;
} 

第九课--查找最值

/*
陈袁鑫
2024.9.25
第九课 查找最值
*/
#include <iostream>
using namespace std;

int main()
{
    //如果题目要你找出最值的话,你会怎么办呢
    //有些人可能会用排序来写,但是,要求位置的话呢
    //这就不得不使用最值方法
    //最值只是一个变量而已,但是,他为什么可以做到查找最值呢
    //我们来看代码
    int ma=0;//最初赋值,可以用INT_MIN,因为你一开始不用最小,之后该怎么求最值呢
    int a[9]={0,1,4,2,3,5,7,6,8};//准备求最大值的数组
    for(int i=1;i<=n;i++){
        if(ma<a[i]){//最大值判断
            ma=a[i];
        }
    }
    cout<<"在a数组中的最大值是:"<<ma<<endl;
    int mi=INT_MAX;//同上
    for(int i=1;i<=9;i++){
        if(mi>a[i]){//最小值判断
            mi=a[i];
        }
    }
    cout<<"在a数组中的最小值是:"<<mi<<endl;
    return 0;
}

第十课--嵌套循环

/*
陈袁鑫
2024.9.26
嵌套循环
*/
#include <iostream>
using namespace std;

int main()
{
    //嵌套循环一般用于输出图形而被使用,下面的是它的格式
    //双重循环格式:
    /*
    for(循环条件1){
	    语句1;
    	for(循环条件2){
	    	语句2;
    	}
    }
    */
    //这样可以输出一个二维图形
    //因为i负责行,j负责列
    //请看下列代码
    for(int i=1;i<=8;i++){
        for(int j=1;j<=8;j++){
            cout<<"*";
        }
        cout<<endl;
    }
    /*
    这样可以输出一个方阵
    就是当i与j的循环次数相等
    之后还可以改一下里面的数据
    */
    //有双重循环就有多重循环
    /*
    for(循环条件1){
	
	语句1;

	for(循环条件2){

		语句2;

		for(循环条件3){	

			语句3; 
		}
	}
}

    */
    //这样子就可以输出更复杂的图形了
    
    return 0;
}

第十一课--数位分离

/*
陈袁鑫
2024.9.26
while循环
*/
#include <iostream>
using namespace std;

int main()
{
    //听说过可以统计数字的循环,但你见过
    //专门应对数位分离的循环吗❓
    //这个循环就是while循环
    /*
    while(怎样才运行){
        代码;
    }
    */
    /*
    for循环一般应用于循环次数已知的情况;
    while循环一般应用于循环次数未知的情况;
    在一般情况下,这两者是可以相互转化的。
    举一个简单较适合用for循环的例子:
    求1-100的和。
    */
    /*
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {

    int sum=0;
	for(int i=1;i<=100;i++)
		sum += i;
	cout<<sum; 
	return 0;
}

    */
   
    /*
     接下来再举一个适用于while循环的例子:
    求输入的一个整数各位数字之和。
    #include<bits/stdc++.h>
    using namespace std;
    int main()
    {
	int n,sum=0;
	cin>>n;
	while(n!=0)
	{
		sum += n%10;
		n /= 10;
	}
	cout<<sum; 
	return 0;
}

    */
    return 0;
}

2级

第一课--定义数组

/*
陈袁鑫
2024.9.25
二级第一课 一维数组的定义
*/
#include <iostream>
using namespace std;

int main()
{
    //数组名代表的不是一个变量,而是一批变量
    //因此不能直接读入整个数组,而是要逐个读入数组元素,通常用循环语句来完成这一功能。
    int a[110];
    //变量类型 变量名[数据范围];
    for(int i=1;i<=10;i++){
        cin>>a[i];
    }
    //也可以单独输入
    cin>>a[11];
    //数组元素的输出通常用循环语句来实现。
    for(int i=1;i<=10;i++){
        cout<<a[i]<<" ";
    }
    //当然,也可以单独输出
    cout<<a[11];
    //一维数组的赋值通常是利用循环语句来实现。
    int b[11];
    b[1]=0;
    //也可以用循环赋值
    for(int i=1;i<=10;i++){
        b[i]=i;
        cout<<b[i]<<endl;
    }
    //数组下标用于标明某一元素在数组中的位置,它与数组元素一一对应。
    //在某个数组中查找满足某个特定条件的数据,可以从数组的第一个至最后一个逐个进行比较。
    return 0;
    
}

第二课--最大最小值查找

/*
陈袁鑫
2024.9.26
最大最小值
*/
#include <iostream>
using namespace std;

int main()
{
    /*
    假设一个最大值 maxx=0 ;
    maxx 依次跟数组中的元素进行比较;
    如果该数组元素大于 maxx ,则将该数组元素值赋值给 maxx ;
    maxx 即为该数组中的最大值。
    参考代码
    #include<bits/stdc++.h>
    using namespace std;
    int n,x[101];
    int maxx=0;//maxx初始值要比任一数组元素的值小
    int main()
    {
	cin>>n; //读入数组元素个数
	for(int i=1;i<=n;i++) //数组赋值
		cin>>x[i];
	for(int i=1;i<=n;i++)  //数组元素依序跟maxx比较
		if(x[i]>maxx) maxx=x[i];
	cout<<maxx; //将最大值输出
	return 0;
    }
    
    */
    /*
    假设一个最大值 maxx=0,并定义一个变量 pos 记录最大值下标;
    maxx依次跟数组中的元素进行比较;
    如果该数组元素大于 maxx,则将该数组元素值赋值给 maxx ,同时将该元素的下标值赋值给 pos ;
    pos 即为该数组中的最大值的下标。
    #include<bits/stdc++.h>
    using namespace std;
    int n,a[105];
        int maxx=0,pos;//maxx初始值要比任一数组元素的值小
    int main()
    {
	cin>>n; //读入数组元素个数
	for(int i=1;i<=n;i++) //数组赋值
		cin>>a[i];
	for(int i=1;i<=n;i++)  //数组元素依序跟maxx比较
		if(a[i]>maxx) maxx=a[i],pos=i; //记录最大值跟最大值的下标
			cout<<pos; //将最大值下标输出
	return 0;
    }
    */
    return 0;
}

 第三课--数组元素的移动、插入、删除

/*
陈袁鑫
2024.9.26
数组元素的移动、插入、删除
*/
#include <iostream>
using namespace std;

int main()
{
    /*
    明明帮助老师按学号顺序把 402 班的数学成绩输入到电脑,完成输完后发现 18 号同学的成绩忘记输入。
    使得后面所有同学的成绩都错位了。能不能设计一个程序把这个同学的成绩插入到正确的位置,使得成绩和学号一一对应?
    解题思路
    从插入位置起所有后面的同学都要向后退一步,先把那个位置空出来,然后就可以插入一个新成员。
    元素的移动:数组元素位置发生变化。
    例如,将数组中位置2的元素移动到位置1,可以写成:
    a[1]=a[2]; //注意此时原位置1的被覆盖。
    又如,将a数组中第一个元素移动到数组末尾,其余数据依次往前平移一个位置,可以按如下步骤实现:
    把第一个元素的值取出放在一个临时单元temp中。
    通过 a[1]=a[2];a[2]=a[3];a[3]=a[4]; ... a[n-1]=a[n] ,实现其余元素前移。
    将 temp 值赋给 a[n]。
    可以用以下语句实现:
    temp=a[1];                          //用temp暂存a[1]
    for (int i=1;i<=n-1;i++)            //2到n位数据前移
	a[i]=a[i+1];
	
    a[n]=temp;                          //把temp存到数据末尾
    */
    /*
    元素的删除:删除数组中某个特定位置的元素。a[5] 的数据虽然仍然存在,但是删除元素之前 n = 5。
    删除后 n = 4,所以 a[5] 的值已经不在被关注,这个值留在数组内并不影响后续的计算了。
    可以用以下语句实现:
    for (int i=3;i<=4;i++)           
    a[i]=a[i+1];
    因此,可以用以下程序解决明明的问题:
    #include<iostream>
    using namespace std;
    int a[1001];
    int main()
    {
	int n,m;
	cin>>n;
	for (int i=1;i<=n;i++)
		cin>>a[i];
	for (int i=n;i>=18;i--)
		a[i+1]=a[i]
	cin>>m;
	a[18]=m;   
	for (int i=1;i<=n+1;i++)
		cout<<a[i]<<" ";
	return 0;  
}

    
    */
    return 0;
}

第四课--选择排序

/*
陈袁鑫
2024.9.26
选择排序
*/
#include <iostream>
using namespace std;

int main()
{
    /*
    今天,数学老师找到了明明,让他把 1000 个学生的数学成绩按从高分到低分输入电脑。
    就像我们排队是从高到矮一样,将同一类型的数据按一定顺序(从大到小或从小到大)排列称为排序。排序的算法有很多,其中选择排序是一种较简单的方法。
    例如:输入 5 个正整数,把这 5 个数按由大到小的顺序排列。
    分析:要把5个数按从大到小顺序排列,则排完后,第一个数最大,第二个数次大,...... 。因此,我们第一步可将第一个位置的数与其后的各个数依次比较。
    若发现有数比它大的,则互相交换位置,这样结束后,第一个位置的数就是最大的数。
    用1号数据和后面2到5号的数据依次比较,确定 “第一大” 的数据。
    -----
    |   |
    20 10 50 40 10
    第一次是 1 号和 2 号比较,20 > 10,所以数据不变。
    -------
    |     |
    50 10 20 40 10
    第二次是 1 号和 3 号比较,20 < 50,所以交换数据。
    -----------
    |         |
    50 10 20 40 10
    第三次是 1 号和 4 号比较,50 > 40,所以数据不变。
    .....
    经过多轮比较,最后确定的顺序是:
    10 10 20 40 50
    这种排序方法叫选择排序:(从大到小)
    for (int i=1;i<=n-1;i++)    //确定第i个位置的数据
	for(int j=i+1;j<=n;j++)   //将第i个数与其后所有数比较
		if (a[i]<a[j])          //若a[j]比a[i]大,则交换数据
		{
			t=a[i];
			a[i]=a[j];
			a[j]=t;
		}
    */
    
    return 0;
}

第五课-sort函数

/*
陈袁鑫
2024.9.26
sort函数
*/
#include <iostream>
using namespace std;

int main()
{
    /*
    sort函数包含在头文件为 algorithm 的c++标准库中
    这里建议用万能头文件:
    #include<bits/stdc++.h>
    sort函数有三个参数:
    第一个是要排序的数组的起始。
    第二个是结束的
    第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。
    sort函数使用模板:
    sort(start,end,排序方法);
    排序方法可以不填,这时候用的是该数组数据类型的默认排序方法。
    下面就具体使用 sort( ) 函数结合对数组里的十个数进行排序做一个说明:
    例一:输入10个整数,从小到大输出。
    {
   int a[10]={9,6,3,8,5,2,7,4,1,0};
   for(int i=0;i<10;i++)
     cout<<a[i]<<" ";
   cout<<endl;
   sort(a,a+10); 
   for(int i=0;i<10;i++)
      cout<<a[i]<<" ";
   cout<<endl;
    下面是运行结果
    输入
    9 6 3 8 5 2 7 4 1 0
    0 1 2 3 4 5 6 7 8 9
    */
    return 0;
}

第六课--输入输出函数

/*
陈袁鑫
输出输入函数
*/
#include<bits/stdc++.h>
using namespace std;
//unsigned long long ;

int main(){
    //我们学习过的 cin、cout,一般情况下,用来输入、输出数据已经足够了。
    //但这种方法电脑的运行效率比较低,尤其是数据量达到 10 万个以上时会超时。
    //为了能够更快输入、输出较多的数据,需要使用格式化输入(scanf)和输出函数(printf)。
    //格式是
   // scanf(格式控制符,变量名);
//    printf(格式控制符,变量名);
//例如:scanf("%d",&a);printf("%d",a);它们也有着和cin与cout一样的好处
//同时也可以输出文字
    //scanf("%d",a+1);  // a+1 是数组元素的第二个元素的地址,所以写 a+1 相当于写 &a[1];  
// 漏了写&,会出现 runtime 错误
//long long a;
//scanf("%d",&a);
//变量是 long long 类型,但是 scanf 的第一个参数格式说明说的是 int 类型。
    return 0;
}

第七课--模拟算法

/*
陈袁鑫
2024.9.30
模拟算法
*/
#include <iostream>
using namespace std;

int main()
{
    //所谓模拟法,就是用计算机模拟某个过程,通过改变数学模型的各种参数,进而观察变更这些参数所引起的过程状态的变化,然后从中得出解答。
    //模拟题的算法一般都不太复杂,关键是所有条件都不能遗漏并要把条件分析清楚。
    //竞赛题目中一般都会给出输入输出样例,以便检查程序的输入输出格式是否正确
    //但这些样例往往会比竞赛时评判所用的测试数据简单,所以你不能满足于通过这些样例。
    //还要尽量自拟一些更复杂、更全面的测试数据来检查程序的正确性
    //比如下面这道题
    /*
    小明每天都可以从妈妈那里领到零花钱,第 1 天可以领到 1 块钱,第2天可以领到 2 块钱......,第 i 天可以领到 i 块钱。
    //如果小明领到零花钱后,手上的零花钱是 3 的倍数时。
    //小明就会将他手上所有零花钱的三分之一存在妈妈那里(假设小明的零花钱从来不花!)。
    //K 天的时候小明手上有多少零花钱呢?
    */
    //是下面的代码
    /*
    int k,s;
    cin>>k;
	for(int i=1;i<=k;i++)
	{
		s=s+i;  //第 i 天的零花钱为i元
		if(s%3==0) s=s/3*2;  //如果手上的零花钱s为3的倍数,存三分之一在妈妈那,自己留三分之二。
	}
	cout<<s;
    */
    //算法就是运用前面学的知识合并到一起来运用的
    
    return 0;
}

第八课--周期问题

/*
陈袁鑫
2024.9.30
周期问题.算法知识
*/
#include <iostream>
using namespace std;

int main()
{
    //在我们的生活中,有很多按照一定规律反复出现、周而复始不断循环的自然现象或客观事件。
    //比如一年中春夏秋冬四季轮回、一周中星期一到星期日7天循环、一天中24个小时不停轮转……像这种带有周期性规律出现的现象。
    //我们统称为周期现象。
    //在数学及信息学中,我们将带有周期性规律的问题,统称为 周期问题 。
    //例如:
    /*
    有一列数,按 5、6、2、4、5、6、2、4、... 排列,第 n 个是几?前 n 个数的和是多少 ?( n <= 10000 )
    int n;
	cin>>n;
	int a = n/4;  //计算有多少个完整的周期
	int b = n%4;  //最后不够一个完整周期的数字有多少个
	cout<< x[b] <<endl;
	cout<<a*17 + s[b];
    */
    return 0;
}

第九课--简单递推

/*
陈袁鑫
2024.9.30
简单递推.递推算法概述
*/
#include <iostream>
using namespace std;

int main()
{
    //递推”是计算机解题的一种常用法。利用“递推法”解题首先要分析归纳出“递推关系”。
    //如经典的斐波那契数列问题,用 f(i) 表示第 i 项的值,则 f(1) = 0 ,f(2) = 。
    //在 n>2 时,存在递推关系:f(n) = f(n-1) + f(n-2) 。递推”是计算机解题的一种常用法。
    //利用“递推法”解题首先要分析归纳出“递推关系”。如经典的斐波那契数列问题,用 f(i) 表示第 i 项的值。
    //则 f(1) = 0 ,f(2) = 1,在 n>2 时,存在递推关系:f(n) = f(n-1) + f(n-2) 。递推”是计算机解题的一种常用法。利用“递推法”解题首先要分析归纳出“递推关系”。如经典的斐波那契数列问题。
    //用 f(i) 表示第 i 项的值,则 f(1) = 0 ,f(2) = 1,在 n>2 时,存在递推关系:f(n) = f(n-1) + f(n-2) 。
    //顺推和倒推
    //顺推,就是从问题的边界条件(初始状态)出发,通过递推关系式依次从前往后递推出问题的解;
    //倒推,就是在不知道问题的边界条件(初始状态)下,从问题的最终解(目标状态或某个中间状态)出发,反过来推导问题的初始状态。
    // 解决递推问题有三个重点:
    //建立正确的递推关系式;
    //分析递推关系式的性质;
    //根据递推关系式编程求解。
    return 0;
}

第十课--简单枚举

/*
陈袁鑫
2024.9.30
简单的枚举.课堂练习1.鸡兔同笼
*/
#include <iostream>
using namespace std;

int main()
{
    //枚举的意思就是把所有情况都看一遍
    //把所有可能的情况输出一遍
    //例如:
    /*
    鸡兔同笼
    鸡兔同笼问题:一个笼子里面有鸡若干只,兔若干只。共有头 50 个,共有腿 160 条。求鸡兔各多少只?
    正确答案是20 30 
    这就是要用双重循环一个一个比较出来的
    有时候枚举需要优化一下
    不然会超时
    实际上枚举最难点在于你要最少循环多少次,才会对,且不超时
    有时要n/2,n/2,n*i+1......
    所以枚举是相对比较难的
    */
    return 0;
}

第十一课--下计计数

/*
陈袁鑫
2023.9.23
10.10做
下标计数
*/
#include <bits/stdc++.h>
using namespace std;

int main()
{
    /*
    题目描述
    奥林匹克运动是人类社会的一个罕见的杰作,它将体育运动的多种功能发挥得淋漓尽致,影响力远远超出了体育的范畴,在当代世界的政治、经济、哲学、文化、艺术和新闻媒介等诸多方面产生了一系列不容忽视的影响。奥林匹克运动有一句著名的格言:“更快、更高、更强(Citius, Altius, Fortius)”。
    迄今为止已经奥运会(夏季)已经举办了 32 届了,在以往的这些盛会中,出现了众多耀眼的体育明星,有人说喜欢菲尔普斯、有人说喜欢博尔特,也有人说喜欢苏炳添...
    现在给每个运动员都编上号,然后大家给自己最喜欢的运动员投票,最后通过将得票最多的推选为最受欢迎的奥运之星。
    因为全球人数太多了,候选人也非常多,通过人力来统计非常麻烦,请你编写程序帮助将奥运之星统计出来,你能做到吗?
    输入格式
     第一行只有一个数:N ( 1 ≤ N ≤ 500000 ),表示参加投票的人数。
    第二行有 N 个正整数,相邻数用空格隔开,所有数均不超过 100000 ,表示这 n 个人的投票情况。
    输出格式
    得票最多的那个数,如果有相同得票的,则输出数值较小的那个数。
        */
        //上面是一道例题
    //它让我们统计所有人的票数
    //下面是它的正确代码:
    
    
    long long n,a[500010],t,ma=INT_MIN,l;
    int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>t;
        a[t]++;//下标计数,统计次数
    }
    for(int i=1;i<=500000;i++){
        if(a[i]>ma){//因为不确定在那,所以全部都便利一遍
            ma=a[i];
            l=i;
        }
    }
    cout<<l;
    return 0;
}
    
    return 0;
}

第十二课--求连续相同的一段数

/*
陈袁鑫
2023.9.23
10.10做
求连续相同的一段数
*/
#include <bits/stdc++.h>
using namespace std;

int main()
{
    /*
    题目描述
    FJ 的农场举行了异一场 USA 奶牛奥林匹克竞赛。N ( 1 <= N <= 100,000 ; N 是一个奇数 ) 只奶牛都已经获得了一个整数分数 S ( 0 <= S <= 10,000 )。
    FJ 必须统计这些分数以便指导他们。帮帮他吧~~给出一个列表,计算最小值、最大值、中间数、众数。中间值是一个值 M ,至少一半的数 <= M ,至少一半的数 >= M 。众数是指出现次数最多的一个数。FJ 知道分数里面只有一个众数。
    输入格式
    第 1 行:一个整数 N 。
    第 2 ~ N+1 行:每一行有一个整数,是一只奶牛的分数。
    输出格式
    四个用空格隔开的整数:最小值、最大值、中间数、众数。
    */
    //上面是一道例题
    //它让我们统计所有人的票数
    //下面是它的正确代码:
    
    
    long long n,a[500010];
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int ma=-1,mi=1000000010,cnt=1,cnt1,ans=0;
    for(int i=1;i<=n;i++){
        if(a[i]>=ma) ma=a[i];
        if(a[i]<=mi) mi=a[i];
        if(i>1){
            if(a[i]==a[i-1]) cnt++;
        }
        else {
            if(cnt>=cnt1)cnt1=cnt,ans=a[i];
            cnt=1;
        }
    }
    cout<<mi<<" "<<ma<<" ";
    if(n%2==0) cout<<a[n/2+1]<<" ";
    else cout<<(a[n/2]+a[n/2+1])/2<<" ";
    cout<<ans<<" ";
    return 0;
}

3级 

第一课--回文数

#include <bits/stdc++.h>
using namespace std;
//unsigned long long ;
void t(string ss){
    cout<<"——————————————————"<<ss<<"——————————————————"<<endl;
} 
void hws(){
    t("判断回文数");
    int n,m;
    cin>>n>>m;
    int s=0,s1=0;
    while(n!=0){
        s=s*10+n%10;
        n/=10;
    }
    while(m!=0){
        s1=s1*10+m%10;
        m/=10;
    }
    if(s==n) cout<<"n是回文数"<<endl;
    else cout<<"n不是回文数"<<endl;
    if(s1==m) cout<<"m是回文数"<<endl;
    else cout<<"m不是回文数"<<endl;
}
void hwspdyzxs(){
    t("回文数的一种组成形式");
    int n;
    cin>>n;
    int s=0;
    while(n!=0){
        s=s*10+n%10;
        n/=10;
    }
    if(s==n){
        cout<<"当n是回文数时,他加上他的倒叙数,也是一个回文数,他是:"<<s+n<<endl;;
    }
    else cout<<"n不是回文数"<<endl;
}
int main(){
    hws();
    hwspdyzxs();
    return 0;
}

第六课--字符串的定义,输出,输入与运用

/*
陈袁鑫
2024.9.30
字符串的定义,输出,输入与运用等等等等;
*/
#include <bits/stdc++.h>
 
using namespace std;
void t(string ss){
    cout<<"----------"<<ss<<"----------"<<endl;
}
void dingyiyufuzhi(){
    t("先定义");
    char c='a';
    char c1='b';
    cout<<"字符c的值是:"<<c<<endl;
    cout<<"字符c1的值是:"<<c1<<endl;
    char c3[101]={'0','a','\0'};//字符数组也是和数组是一样的,赋值也和它一样
    //后面记得要加\0,不然他会一直输出上一个(只会输出一次)
    cout<<"c3数组里存的值是:"<<c3[0]<<" "<<c3[1]<<endl;
}
void shuru(){
    t("输入");
    char a1,a2,a3;
    cin>>a1;
    scanf("%c",&a2);
    a3=getchar();//这里也可以表示输入,上一个是换行符
    
    //注意 字符有着独特的scanf输入
    //他们代表的输入是%c
    cout<<"字符a1里输入的数是:"<<a1<<endl;
    cout<<"字符a2里输入的数是:"<<a2<<endl;
    cout<<"字符a3里输入的数是:"<<a3<<endl;
}
void shuchu(){
    t("输出");
    char b1,b2;
    //字符的输出可以是cout
    //也可以用2级内容:printf
    b1='#';
    b2='@';
    cout<<"b1里赋值的字符是:"<<b1<<endl;
    printf("b2里赋值的字符是:%c\n",b2);
}
void yushuzuzhijiandeguanzi(){
    t("与数字之间的关系");
    //每一个字符都有一个对应的ASCLL码值
    //比如:
    char c=97;
    cout<<"c字符对应的字符是:"<<c<<endl;
    char b=c+1;
    cout<<"b字符对应的字符是:"<<b<<endl;
}
int main()
{
    dingyiyufuzhi();
    shuru();
    shuchu();
    yushuzuzhijiandeguanzi();
    return 0;
}

4级

第九课--的语法知识

/*
陈袁鑫
2024.12.24
函数的语法知识
*/
#include <bits/stdc++.h>
using namespace std;
void tt(string ss){
    cout<<"————————————————"<<ss<<"——————————————————"<<endl;
}
int ans(int s){
    unsigned long long ans=1;
    for(int i=1;i<=10;i++){
        ans*=i;
    }
    return ans;
}
void hsdy(){
    tt("函数的定义");
    cout<<"我们曾经学习了程序设计中的三种基本控制结构(顺序、分支、循环)。"<<endl;
    cout<<"用它们可以组成任何程序。"<<endl;
    cout<<"但在应用中,还经常用到子程序结构。"<<endl;
    cout<<"通常,在程序设计中,我们会发现一些程序段在程序的不同地方反复出现。"<<endl;
    cout<<"此时可以将这些程序段作为相对独立的整体,用一个标识符给它起一个名字。"<<endl;
    cout<<"凡是程序中出现该程序段的地方,只要简单地写上其标识符即可。这样的程序段,我们称之为子程序。"<<endl;
    cout<<"子程序的使用不仅缩短了程序,节省了内存空间及减少了程序的编译时间,而且有利于结构化程序设计。"<<endl;
    cout<<"因为一个复杂的问题总可将其分解成若干个子问题来解决。"<<endl;
    cout<<"如果子问题依然很复杂,还可以将它继续分解,直到每个子问题都是一个具有独立任务的模块。"<<endl;
    cout<<"这样编制的程序结构清晰,逻辑关系明确,无论是编写、阅读、调试还是修改,都会带来极大的好处。"<<endl;
    cout<<"在一个程序中可以只有主程序而没有子程序(本章以前都是如此),但不能没有主程序,也就是说不能单独执行子程序。"<<endl;
    cout<<"在此之前,我们曾经介绍并使用了C++提供的各种标准函数,如abs(),sqrt()等等"<<endl;
    cout<<"这些系统提供的函数为我们编写程序提供了很大的方便。"<<endl;
    cout<<"比如:求sin(1)+ sin(2)+...+sin(100)的值。但这些函数只是常用的基本函数,编程时经常需要自定义一些函数。"<<endl;
    cout<<"例6.1 求:1!+2!+3!+……+10!"<<endl;
    cout<<"意思是输出10的阶乘"<<endl;
    cout<<ans(10)<<endl;
}
int main()
{
    hsdy();
    return 0;
}

第十课--结构体

在实际问题中,一组数据往往具有不同的数据类型。例如,人口大普查时,我们需要记录每一位公民的姓名,年龄,性别,住址,身份证号码。这些信息分别要用整型,字符型,字符串型来记录。为了解决问题,C++语言给出了另一种构造数据类型——“结构体”,它在数据存储方面相当于其他高级语言中的记录,但它有着面向对象的优势。

一、结构体定义和操作

1. 定义结构体及结构体变量

结构体变量的定义有两种方式:

定义结构体的同时定义结构体变量

struct 结构体名 {  //其中 struct 是关键字
	成员表   //可以有多个成员
	成员函数  //可以有多个成员函数,也可以没有
} 结构体变量表; //可以同时定义多个结构体变量

Copy

结构体变量名列表的各个变量用“,”隔开。例如:

struct DATA{
	int a[2];     //成员为一个数组
	int c;      
}data_a,data_b;

Copy

当然,我们也可以先定义结构体再定义结构体变量

struct 结构体名{
	成员表
	成员函数
};

结构体名  结构体变量表;//同样可以同时定义多个结构体变量

Copy

例如:

struct DATA{
	int a[2];                      
	int c;      
};
DATA data_a,data_b;//这种定义方式与上一种方式的效果是相同的

Copy

在定义结构体变量时注意,结构体变量名和结构体名不能相同。在定义结构体时,系统对之不分配实际内存。只有定义结构体变量时,系统才为其分配内存。

2.成员调用

结构体变量与各个成员之间引用的一般形式为:

结构体变量名. 成员名

对于上面定义的结构体变量,我们可以这样操作:

cin>>data_a.a[0]>>data_a.a[1];  //一般情况下不能写 cin>>data_a;

int a=data_a.a[0]+data_a.a[1];    //就像用整形变量一样用a[0]、a[1]

data_b=data_a;       //结构体之间的相互赋值是合法的

data_a.c=0;       //就如同给整形变量赋值

Copy

实际上结构体成员的操作与该成员类型所具有的操作是一致的。

成员运算符“.”在存取成员数值时使用,其优先级最高,并具有左结合性。在处理包含结构体的结构体时,可记作:

strua. strub. membb

Copy

这说明结构体变量 strua 有结构体成员 strub;结构体变量 strub 有成员 membb。

3.成员函数调用

结构体成员函数调用的一般形式为:

结构体变量名. 成员函数  

Copy

结构体成员函数默认将结构体变量作为引用参数。

二、结构体操作实例

现在,我们先定义一个简单的结构体,这个结构体将用来记录一个学生的大致情况,所以它的成员应该有学号、姓名、性别、年龄、成绩、家庭住址等。

#include<iostream>
using namespace std;
struct student{
	int num; //学号
	char name[21]; //姓名
	char sex; //性别
	int age; //年龄
	float score; //成绩
	char address[51]; //家庭住址
}; //此处不可忽略分号
struct student a,b;
int main()
{
	cin>>a.num>>a.name>>a.sex>>a.age>>a.score>>a.address;
	cin>>b.num>>b.name>>b.sex>>b.age>>b.score>>b.address;
	cout<<a.num<<' '<<a.name<<' '<<a.sex<<' '<<a.age<<' '<<a.score<<' '<<a.address<<endl;
	cout<<b.num<<' '<<b.name<<' '<<b.sex<<' '<<b.age<<' '<<b.score<<' '<<b.address<<endl;
	return 0;
}

 

5级

第七课--字符串

/*
陈袁鑫
2024.12.25
字符串;
*/
#include <iostream>
using namespace std;

void l(){cout << endl;}
void t(string t) {cout << endl << "***** " << t << " *****" << endl;}

void ChuangJian() {
    t("创建");
    // 1.使用 char 变量名; 创建
    char c1 = 'a', c2 = '+', 
        c3 = 'a' + 1,// 'b'
        c4 = 99;// ASCII码为99的字符'c'
}

void ShuRu() {
    t("输入");
    char c2;
  
    // 下面例子分别试输入"12345回车"和"1回车2回车3回车"查看结果
  
    // 1.使用cin输入
    cin >> c2;
    cout << "3.1 c2 = " << c2 << endl;
  
    // 2.使用 * 字符变量=getchar(); * 输入;
    // !!! 可以接收回车换行符赋值给该字符(包括上一个输入结束时的回车)
    c2 = getchar();// 这里过滤接收上一条输入语句“cin >> c2;”的回车换行符
    c2 = getchar();// 这里可以获得想要输入的字符给c2
    cout << "3.2-1 c2 = " << c2 << endl;
  
    c2 = getchar();// 如果上一个getchar()输入时按了回车键,那么这个字符将会是换行
    cout << "3.2-2 c2 = " << c2 << endl;
    cout << "End" << endl;
  
    // 3.使用scanf输入
    scanf("%c", &c2);
    printf("3.3 c2 = %c\n", c2);
}

void ShuChu() {
    t("输出");
    char c1 = 'c', c2;
    // 1.使用cout输出
    cout << "c1 = " << c1 << endl;
  
    // 2.使用 *printf(\"%c\",变量名);* 输出
    printf("c2 = %c\n", c2);
  
    // 3. putchar()
    char c3 = 'k';
    putchar(c3);
}

void HeShuZiGuanXi() {
    t("和数字之间的关系");
    // 特殊记忆几个ASCII数值:'0'、'A'、'a' 的ASCII码是48、65、97
  
    // 1.字符和整数可以互相转换,对应关系参考ASCII码表
    char c6 = 97;// 在ASCII码表中97对应'a'字符
    char c7 = c6 + 1;
    int k7 = c7;
    cout << "c7 = " << c7;
    l();
    cout << "k7 = " << k7;
    l();
  
    // 2. 0-9字符减去0字符可以转换成数字
    char c5 = '5';
    int k5 = c5 - '0';
    cout << "k5 = " << k5 << endl;
  
    // 3.通过ASCII码表输出英文字母表
    for(char i='a'; i<='z'; i++)    cout << i << " ";
    l();
  
    // 4.大小写字母转换
    char c1 = 'd', c2 = 'A' + (c1 - 'a'),
        c3 = 'E', c4 = 'a' + (c3-'A');
    cout << c1  << "->" << c2 << endl << c3  << "->" << c4 << endl;
}
void ChuangJian1() {
    t("创建");
  
    // 1. 通过char 变量名[长度] 创建
    char c1[20];
}
void FuZhi() {
    t("赋值");
  
    // 1. 创建时通过{}赋值
    // !使用这种方式赋值时一定要多加一个'\0'字符
    // ! 声明创建后不能再用{}给整个字符数组赋值
    char str1[4] = {'H', 'i', '!', '\0'};
    // !str1中的'\0'不计入通过strlen()获取的长度中
    cout << "1. str1 = " << str1 << ",长度为" << strlen(str1) << endl;
  
    // 2. 创建时通过字符串常量""赋值
    // !说明:由于字符数组要在结束位置保存一个'\0'字符,所以指定长度要比实际的长度大1
    // 错误示例:char str2[5] = "Hello";
    char str2[6] = "Hello";
    cout << "2. str2 = " << str2 << ",长度为" << strlen(str2) << endl;
  
    // 3. 创建时赋值的情况可以不指定长度,此时长度默认为该字符数组常量的长度
    char str3[] = "Hello";
    char str4[] = {'W', 'e', '\0'};
    cout << "3.1 str3 = " << str3 << ",长度为" << strlen(str3) << endl;
    cout << "3.2 str4 = " << str4 << ",长度为" << strlen(str4) << endl;
  
    // 4. 通过下标对字符数组中的某个字符赋值
    char str5[] = "Hello";
    cout << "4.1 str5 = " << str5 << ",长度为" << strlen(str5) << endl;
    str5[1] = 'i';
    cout << "4.2 str5 = " << str5 << ",长度为" << strlen(str5) << endl;
  
    // 4. 输入赋值(见输入语法)
  
    // !说明1. 声明创建后不能用""和{}这两种方式再对整个数组直接赋值
    // str1 = {'Y', 'o', 'u'}; // !这行代码放在这里是错误的
  
    // !说明2. 使用""赋值时字符数组会自动在结尾处加结束标志符'\0'
    // 但使用{}赋值时需要手动加一个字符'\0',不然会出现预想不到的错误
    // 下面例子中str41会输出为WeHello,因为str41结尾没有\0,连到了str31的地址
    char str31[] = "Hello";
    char str41[] = {'W', 'e'};// 此句代码有问题,漏加'\0'
  
    cout << "说明2 str31 = " << str31 << ",长度为" << strlen(str31) << endl;
    cout << "说明2 str41 = " << str41 << ",长度为" << strlen(str41) << endl;// 会输出WeHello
  
}

void ShuChu1() {
    t("输出");
    char str[6] = "Hello";
  
    // 1. 通过 cout << 变量名; 输出
    cout << "1. str = " << str << endl;
  
    // 2. 通过 printf("%s", 变量名); 输出
    printf("2. str = %s\n", str);
  
    // 3. 通过下标输出
    for(int i = 0; i < 5; i++) {
        cout << str[i] << " ";
    }
}
void ShuRu1() {
    t("输入");
    char str[5];
  
    // 1. cin >> str
    // ! 无法输入空格
    cin >> str;
    cout << endl << "1. str = " << str << endl;
  
    // 2. cin.getline(数组名, 读入长度, 结束的字符(可不填,默认回车符))
    // 可读入空格
    getchar();// 先接收上面输入的回车符
    cin.getline(str, 5);
    cout << endl << "2. str = " << str << endl;
  
    // 3. scanf("%s", 地址)。以空格或回车符作为输入的结束,字符数组名本身可以当地址
    scanf("%s", str);
    cout << endl << "3. str = " << str << endl;
  
    // 4. gets(地址);。 用 gets 读入整个数组,
    // 能输入空格(C++14版本后无法使用)
    getchar();// 先接收上面输入的回车符
    gets(str);
    cout << endl << "4. str = " << str << endl;
}
void HuoQuChangDu() {
    t("获取长度");
    char str1[4] = {'H', 'i', '\0'},
        str2[] = "abcde";
  
    // 1. strlen() 获取字符串的实际长度(不包括结尾的空字符'\0')。
    // !需要引入<cstring>库
  
    // 2. sizeof() 返回包含'\0'在内的长度
  
    cout << "str1长度为 " << strlen(str1) << "/" << sizeof(str1) << endl;
    cout << "str2长度为 " << strlen(str2) << "/" << sizeof(str2) << endl;  
}
void QiTaGongNengHanShu() {
  
    // strcmp 比较
    // strcat
  
    // strcpy
    // 
}
void ChuangJian3() {
    t("创建");
    // 1.声明和初始化字符串 
    // 需要引入<string>库
    string str0;
    string str1 = "Hello";          // 直接赋值初始化  
    string str2(5, 'C');            // 使用字符和长度初始化,5个C连成的字符串"CCCCC"  
    string str3 = str1 + ", World!"; // 通过拼接初始化  
  
    // 字符串输入输出  
    cout << "1. str1: " << str1 << endl;  
    cout << "2. str2: " << str2 << endl;  
    cout << "3. str3: " << str3 << endl;  
}
void PinJie() {
    t("拼接");
    // 1. 使用+符号拼接
    string str1 = "Hello";
    str1 += ",OhYeah";
    cout << "1. str1: " << str1 << endl;  
}
void XiuGai() {
    t("修改");
    string str1 = "Hello";
    // 1. 通过下标访问单个字符
    cout << "1. " << str1[0] << " " << str1[4] << endl;
  
    // 2.通过下标修改单个字符
    str1[0] = 'h';
    cout << "2. " << str1[0] << " " << str1[4] << endl;
  
    // 3. 重置整个字符串
    str1 = "New";
    cout << "3. " << str1 << endl;
}

void ChangDu() {
    t("获取字符串长度");
    // 1. .size()
    // 2. .length() 
    // ! 二者是等价的 
    string str1 = "Hello";
    cout << "1. Hello的长度: " << str1.length() << " " << str1.size() << endl;  
}
void BianLiMeiGeZiFu() {
    t("遍历每个字符");
    // 1. 根据长度和下标访问
    string str1 = "Hello";
    for(size_t i=0; i<str1.size(); i++) {
        cout << "1. Hello第" << i << "个字符是 " << str1[i] << endl;
    }  
}

void ChaZhaoZiChuan() {
    t("查找子串");
    // 1. .find(子串) 返回下标位置,没有找到则返回-1(string::npos)
    string str1 = "Hello";
    cout << "1. Hello中l的位置在" << str1.find("l") << endl;
    cout << "2. Hello中He的位置在" << str1.find("He") << endl;
    cout << "3. Hello中k的位置在" << str1.find("k") << endl;
    cout << "4. Hello中k的位置是否是-1:" << (str1.find("k")==-1) << endl;
  
    // str1 = "My World";
    size_t found = str1.find("World");  
    if (found != string::npos) {  
        cout << "5. 使用string::npos判断:'World' found at index: " << found << endl;  
    } else {  
        cout << "5. 使用string::npos判断:'World' not found" << endl;  
    }
}
void BiJiaoDaXiao() {
    t("比较大小");
    // 1. 使用大小关系运算符比较 
    // 从左往右比较相应位置字符的ASCII码值,能区分大小时即返回结果
  
    string str1 = "Hello", str2 = "Ab", str3 = "Ac", str4 = "Ac";
    cout << "1. Hello>Ab:" << (str1>str2) << endl;
    cout << "2. Hello<Ab:" << (str1<str2) << endl;
    cout << "3. Ab>Ac:" << (str2>str3) << endl;
    cout << "4. Ac==Ac:" << (str3==str4) << endl;
  
}

void TiQuZiChuan() {
    t("提取子串");
    // 1. .substr(开始位置, 长度(不写的话默认到最后))
    string str1 = "Hello";
    cout << "1. Hello中第2~4位置之间的字符子串:" << str1.substr(1, 3) << endl;
}
//______________________________________________________-
void ChaRuZiChuan() {
    t("插入子串");
    // 1. .insert(开始插入的位置,要插入的子串)
    string str1 = "Hello";
    str1.insert(5, " World");
    cout << "1. 在Hello后面插入 World:" << str1 << endl;
}

void ShanChuZiChuan() {
    t("删除子串");
    // 1. .erase(开始位置, 长度)
    string str1 = "Hello";
    str1.erase(1, 2);
    cout << "1. 删除Hello中的el:" << str1 << endl;
}

void TiHuanZiChuan() {
    t("替换子串/先删除后插入");
    // 1. .replace(要删除的子串的开始位置,要删除子串的长度,新插入的子串)
    string str1 = "It's Your World";
    str1.replace(5, 4, "Our");
    cout << "1. 将Our替换Your后:" << str1 << endl;
  
}

void ShuChu3() {
    t("输出");
    // 1. 使用cout输出
    string str1 = "ab c";
    cout << "1. 使用cout输出" << str1 << endl;
  
    // 2. 不能使用scanf()
    // ! printf("%s", str1);是错误的
}

void ShuRu3() {
    t("输入");
  
    string str1; 
    // 1. 使用cin,不能获取空格
    cin >> str1;
    cout << "1. cin >> str1: " << str1 << endl;  
   
    // 2. 使用getline(cin, 地址),可以获取空格
    getchar();// 用于获取上一个输入内容的回车键
    getline(cin, str1);
    cout << "2. getline(cin, str1): " << str1 << endl; 
  
    // 3. 不能使用scanf()
    // ! scanf("%s", str1);是错误的
}

int main() {
    ChuangJian();
    ShuRu();
    ShuChu();
    HeShuZiGuanXi();
    ChuangJian1();
    FuZhi();
    ShuChu1();
    ShuRu1();
    HuoQuChangDu();
    QiTaGongNengHanShu();
    ChuangJian3();
    PinJie();
    XiuGai();
    ChangDu();
    BianLiMeiGeZiFu();
    ChaZhaoZiChuan();
    BiJiaoDaXiao();
    TiQuZiChuan();
    ChaRuZiChuan();
    ShanChuZiChuan();
    TiHuanZiChuan();
    ShuChu3();
    ShuRu3();
    return 0;
}

6级

第五课---尺取理论知识

尺取法是一种线性算法,也是一种高效的枚举区间的方法。

记 (l,r) 两个端点为一个序列内以 l 为起点的最短合法区间,如果 r 随 l 的增大而增大的话,我们就可以使用尺取法。

具体的做法是:

  1. 初始化左右端点

  2. 不断扩大右端点,直到满足条件

  3. 如果第二步中无法满足条件,则终止,否则更新结果

  4. 将左端点扩大1,然后回到第二步

因为 r 随 l 增大而增大,所以 r 只有 n 次变化的机会,所以时间复杂度为 O(n) 。

经典例子

给定一个长度为 n 的数列 a_1, a_2, ..., a_na1​,a2​,...,an​ 及整数 S ,求不小于 S 的连续子序列的和的最小值,假设解肯定存在。

input

n=10,S=15

a= {5,1,3,5,10,7,4,9,2,8}

尺取法示意图

首先,取得满足条件的最小序列,然后依次将响右移动,若 i 向左移动的过程中序列仍然满足条件,则不移动,否则将也向右移动。

在移动的过程中记录 j-i 的最小值。

第十一课--二维前缀和

二维前缀和,建立在一维前缀和之上,我们要求一个矩阵内一个任意的子矩阵的数的和,我们就可以用二维前缀和。

我们可以感性的将其理解为建立在二维平面上的前缀和,如下图:

红色区域所有数的和即为二维前缀和中点(i,j) 的值。

一、如何预处理

类比一维前缀和,我们可以在O(n)的时间复杂度下预处理,如下代码:

    s[i] = s[i-1] + a[i];

Copy

那么对于二维前缀和,我们怎么预处理呢?

先给出算式:

    Map[i][j] + Map[i-1][j] + Map[i][j-1] - Map[i-1][j-1] + a[i][j];

(a 数组是原数据数组,Map数组用于存放前缀和)

类比一维前缀和,因为我们从左到右在计算 a[i] 的时候已经知道了a[i-1] 的值,所以同理,我们从左上向右下在计算 Map[i][j] 的时候已经知道了它右上所有点的前缀和,也就是知道 Map[i-1][j]、Map[i][j-1] 和 Map[i-1][j-1] 的值,那么现在考虑为什么要做如上的运算。

其中,Map[i][j] 的初始值即为点 (i,j) 的权值,如图:

 

那么现在,我们要求前缀和,也就是要加上下图中橙色区域:

而我们加上的 Map[i-1][j] 即为下图蓝色区域:

加上的 Map[i][j-1] 即为下图绿色区域:

然后我们会发现,有一部分重叠了,如下图紫色区域:

而这部分就是我们要减去的 Map[i-1][j-1] 。

那么我们的预处理就完成了。

时间复杂度:O(n×m),与一维中的O(n)预处理同理。

二、如何查询

依然是类比一维前缀和,对于查询区间 (l,r) 的值,我们可以用如下代码进行 O(1) 的查询:

    sum=a[r]-a[l-1];

也就是说,用右端点的前缀和值减去左端点 -1 的前缀和值即得到了区间 (l,r) 的和,如下图:

那么对于二维前缀和,我们有应该怎么办呢?

对于计算矩形(x1,y1)∼(x2,y2)的和,先给出如下算式:

    sum = Map[x2][y2] - Map[x1-1][y2] - Map[x2][y1-1] + Map[x1-1][y1-1];

下面来理解算式:

现在我们要求下图中红色区域的权值和:

而我们已经预处理好了前缀和,但是我们还不直接知道矩形(x1,y1)∼(x2,y2)的权值和,那么我们考虑怎么减去那部分。

我们已经知道了 Map[x2][y2] ,而我们需要减去下图中橙色区域:

那么我们先减去 Map[x1−1][x2] ,也就是下图中蓝色区域:

然后再减去 Map[x2][y1−1] ,也就是下图中绿色区域:

然后,我们发现我们多减去了一部分,要把它加回来,而这部分就是 Map[x1−1][y1−1] ,如下图紫色部分:

这样,我们就成功的得到了需要求和的部分的值。

时间复杂度:O(1),与一维前缀和的 O(1) 同理。

7级

第六课--动态数组


/*
陈袁鑫
2023.9.23
10.14做
C07.L06.STL之动态数组.概述
*/
#include <bits/stdc++.h>
using namespace std;
void t(string ss){
    cout<<"————————————————"<<ss<<"——————————————————"<<endl;
}
void dingyi(){
    t("定义");
    //头文件要用 #include<vector> ( 用万能头文件也可以)
    vector<int> dc;
    cout<<"vector<数据类型> 变量名"<<endl;
}
void shuruandshuchu(){
    t("输入&输出");
    vector<int> dc;
    int x,y,z;
    cin>>x>>y>>z;
    dc.push_back(x); 
    dc.push_back(y);
    dc.push_back(z);
    cout<<"dc[0]="<<dc[0]<<endl;
}
void shuchuchangdu(){
    t("输出长度&清空&判空");
    vector<int> dc;
    dc.push_back(1); 
    dc.push_back(2);
    dc.push_back(3);
    dc.push_back(4); 
    dc.push_back(5);
    dc.push_back(6);
    dc.push_back(7); 
    dc.push_back(8);
    dc.push_back(9);
    cout<<"dc的长度是"<<dc.size()<<endl;
    dc.clear();
    cout<<"dc现在是否为空"<<dc.empty()<<endl;
}
int main()
{
    dingyi();
    shuruandshuchu();
    shuchuchangdu();
    return 0;
}

 

第八课--二分查找&二分答案

/*
陈袁鑫
2024.12.15
C06.L06二分查找与二分答案
*/
#include <iostream>
using namespace std;
void t(string ss){
    cout<<"——————————————————"<<ss<<"——————————————————————"<<endl;
}
void erfenchazhao(){
    t("二分查找知识点讲解");
    cout<<"二分查找只是一个算法,不是什么函数"<<endl;
    cout<<"所以会相对来说简单一些"<<endl;
    cout<<"先看例题:"<<endl;
    cout<<"题目描述"<<endl;
    cout<<"请在一个有序递增数组中(不存在相同元素),采用二分查找,找出值 x 的位置,如果 x 在数组中不存在,请输出 -1 !"<<endl;
    cout<<"输入格式"<<endl;
    cout<<"第一行,一个整数 n ,代表数组元素个数 ( n <= 600000 )"<<endl;
    cout<<"第二行,n 个数,代表数组的 n 个递增元素 ( 1 <= 数组元素值 <= 2000000 )"<<endl;
    cout<<"第三行,一个整数 x ,代表要查找的数 ( 0 <= x <= 2000000 )"<<endl;
    cout<<"输出格式"<<endl;
    cout<<"按题意输出位置或者 -1 。"<<endl;
    cout<<"样例"<<endl;
    cout<<"输入数据 1"<<endl;
    cout<<"10"<<endl;
    cout<<"1 3 5 7 9 11 13 15 17 19"<<endl;
    cout<<"3"<<endl;
    cout<<"输出数据 1"<<endl;
    cout<<"2"<<endl;
    cout<<"完成程序"<<endl;
    /*
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    cout<<""<<endl;
    */
    /*
    int n,a[1000005],x;
    scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	scanf("%d",&x);
	a[n+1] = 2000001;
	a[0] = -1;
	int L=0, R=n+1, mid; //左右指针初始化
	
	while(L+1<R)
	{
		mid = (L+R)/2;
		if(a[mid]==x)
		{
			cout<<mid;
			return 0;
		}
		else
		{
			if(a[mid] > x)
				L = mid;
			else
				R = mid;
		}
	}
	cout<<-1;
    */
    cout<<"上面是例子,参考一下"<<endl;
}
void efda(){
    t("二分答案");
    cout<<"二分答案是二分的一种进阶,所以讲了没必要,有点难"<<endl;
}
int main()
{
    erfenchazhao();
    efda();
    return 0;
}

 

第九课--栈的运用

/*
陈袁鑫
2023.9.23
10.10做
栈的应用
*/
#include <bits/stdc++.h>
using namespace std;
void t(string ss){
    cout<<"————————————————"<<ss<<"——————————————————"<<endl;
}
void dingyi(){
    t("定义");
    cout<<"栈的格式:stack<数据类型>栈名"<<endl;
}
void ruzhanyuchuzhan(){
    t("入栈与出栈");
    stack<int>s;
    int a,b;
    cin>>a>>b;
    s.push(a);
    s.push(b);
    cout<<"将栈顶元素出栈,元素是:"<<s.top()<<endl;
    s.pop();
    cout<<"出栈后的栈顶元素是:"<<s.top()<<endl;
}
void qingkong(){
    t("清空");
    stack<int>s;
    s.push(5);
    cout<<"输出栈是否为空:"<<s.empty()<<endl;
    s.pop();
     cout<<"输出栈是否为空:"<<s.empty()<<endl;
}
void fangwenchangdu(){
    t("访问长度");
    stack<int> s;
    s.push(5);
    cout<<"s的长度为:"<<s.size()<<endl;
}
void bianli(){
    t("遍历");
    stack<int> s;
    for(int i=1;i<=5;i++){
        int t;
        cin>>t;
        s.push(t);
    }
    cout<<"输出入栈的元素"<<endl;
    while(!s.empty()){
        cout<<s.top()<<" ";
        s.pop();
    }
}
int main()
{
    dingyi();
    ruzhanyuchuzhan();
    qingkong();
    fangwenchangdu();
    bianli();
    return 0;
}

第十课--队列

双向队列

/*
陈袁鑫
2023.9.23
10.10做
栈的应用
*/
#include <bits/stdc++.h>
using namespace std;
void t(string ss){
    cout<<"————————————————"<<ss<<"——————————————————"<<endl;
}
void dingyi(){
    t("定义");
    cout<<"队列的格式:deque<数据类型>队列名"<<endl;
}
void ruzhanyuchuzhan(){
    t("入队列与队列");
    deque<int>s;
    int a,b;
    cin>>a>>b;
    s.push_front(a);
    s.push_back(b);
    cout<<"将队列顶元素出队列,元素是:"<<s.front()<<endl;
    s.pop_front();
    cout<<"出队列后的队列顶元素是:"<<s.front()<<endl;
}
void qingkong(){
    t("清空");
    deque<int>s;
    s.push_front(5);
    cout<<"输出队列是否为空:"<<s.empty()<<endl;
    s.pop_front();
     cout<<"输出队列是否为空:"<<s.empty()<<endl;
}
void fangwenchangdu(){
    t("访问长度");
    deque<int> s;
    s.push_front(5);
    cout<<"s的长度为:"<<s.size()<<endl;
}
void bianli(){
    t("遍历");
    deque<int> s;
    for(int i=1;i<=5;i++){
        int t;
        cin>>t;
        s.push_front(t);
    }
    cout<<"输出入队列的元素"<<endl;
    while(!s.empty()){
        cout<<s.front()<<" ";
        s.pop_front();
    }
}
int main()
{
    dingyi();
    ruzhanyuchuzhan();
    qingkong();
    fangwenchangdu();
    bianli();
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值