蓝桥杯算法笔记(一)
文章目录
1 语言基础
1.1 编程基础
1.1.1 C++基础格式与版本选择
01.C++版本区别与选择
C++98:第一个版本。
C++03:值的初始化引入其中。
C++11(蓝桥杯选用):引入了Lambda表达式、委托构造函数、统一初始化语法、自动类型推导auto、decltype、Rvalue等。
C++14:添加了多态Lambda、数字分隔符、通用Lambda捕获、变量模板、二进制整数文字、引用字符串等。
C++17:引入了折叠表达式、十六进制浮点文字、u8字符文字、带有初始化程序的选择语句、内联变量等。
02.C++代码格式与语法基础
#include <bits/stdc++.h> //万能头文件
using namespace std;
int main(){ //main函数是C++内置的启动函数
cout<<"hello,world!"<<endl; //cout是输出流,更细节的是cout是输出到屏幕。endl是换行符
printf("hello,world!");
return 0; //函数遇到return结束,返回0
}
输出结果:
hello,world!
hello,world!
#include <bits/stdc++.h>
using namespace std;
int main(){
int x=2;
double c=3.14;
char z='a';
char s[]="hello";
bool b=true; //布尔值,即真假值
cout<<x<<'\n';
cout<<c<<'\n';
...
return 0;
}
输出整型、浮点型、字符、字符串、布尔型等。
03.手撕代码
数组:
#include <bits/stdc++.h>
using namespace std;
//const表示变量,后续不可被修改
const int N=1e5+9;
int a[N];
int main(){
...
return 0;
}
typedef:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll
const int N=1e5+9;
ll a[N];
int main(){
...
return 0;
}
字符串:
#include <bits/stdc++.h>
using namespace std;
int main(){
char s[]="hello";
for(int i=0;i<5;++i){
cout<<s[i];
}
cout<<'\n';
cout<<s<<'\n';
return 0;
}
输出偶数:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n=10;
for(int i=1;i<=n;++i){
if(i%2==0)cout<<i<<'\n';
}
return 0;
}
1.1.2 输入输出
01.scanf和printf
例1:
int main(){
double a,b; //声明
scanf("%lf %lf",&a,&b);
printf("%.2lf,%.3lf",a,b);
return 0;
}
例2:%s输入遇到空格或者回车就会停下
int main(){
char s[10];
scanf("%s",s); //此时的s代表的是s这个字符串的首地址
printf("%s",s);
return 0;
}
scanf("[^\n]",s); //[]是一个正则表达式,表示只要不是回车就都进去。
02.cin 和 cout
如下:
int mian(){
int a,b;
cin>>a>>b; //自动判断变量类型
cout<<a<<' '<<b<<'\n';
return 0;
}
int main(){
double a,b;
cin>>a>>b;
cout<<fixed<<setprecision(3)<<a<<' '<<b<<'\n'; //setprecision()设置保留小数点后三位。
return 0;
}
cin 输入字符串的时候也是遇到空格或者回车就结束。使用getline()函数可以输入空格
int main(){
string s;
getline(cin,s);
cout<<s;
return 0;
}
03.取消同步流
由于 cin 和 cout 需要自动判断变量类型等内部原因,读写效率比scanf和printf更低。
当数据量较大时,可能导致程序运行超时。
我们可以取消同步流来加速cin和cout.
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); //取消同步流
int x;cin>>x;
cout<<x<<'\n';
return 0;
}
代码示例:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N=150;
int a[N];
int main(){
//取消同步流
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n;cin>>n;
for(int i=1;i<=n;++i)cout<<a[i]; //遍历
for(int i=n;i>=1;--I)cout<<a[i]; //逆遍历
return 0;
}
字符串输入输出:
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N=150;
char s[N];
int main(){
//取消同步流
ios_sync_with_stdio(0),cin.tie(0),cout.tie(0);
cin>>s+1; //从s[1]的位置开始输入
for(int i=1;s[i];++i)cout<<s[i]; //s[i]如果等于 '\0',结束循环
return 0;}
1.1.3 string的使用
01.string简介
string是C++标准库的重要组成部分,主要用于字符串处理,string库包含在头文件#include中。(包含万能头文件#include <bits/stdc++.h>可以不写string头文件)
string和cahr[]不同,string实现了高度封装,可以很方便的完成各种字符串操作,比如拼接、截取、匹配等等。
string的特性:
- 字符串管理:string封装了字符串的存储和管理。它可以自动处理字符串的内存分配和释放,避免了手动管理内存的麻烦。
- 动态大小调整:string可以根据需要自动调整字符串的大小。在添加或删除字符时,string会自动调整内部的存储容量,确保足够的空间来容纳字符串。
- 安全性:string提供了一些方法来确保字符串的安全性。例如,它提供了越界访问检查,以避免访问超出字符串范围的字符。
- 迭代器支持:string支持迭代器,可以使用迭代器遍历字符串中的字符,进行字符级别的操作。
- 兼容性:string是C++标准库的一部分,因此在C++中广泛使用,并且与其他标准库组件和C++语言特性兼容。
02.string的声明和初始化
#include <iostream>
#include <string>
//using namespace std;
int main(){
//声明并初始化一个空字符串
std::string str1;
//使用字符串自变量初始化字符串
std::string str2 = "hello,world!";
//使用另一个std::string 对象来初始化字符串
std::string str3 = str2;
//使用部分字符串初始化字符串,substr()子串截取函数
std::string str4 = str2.substr(0,5);
//使用字符数组初始化字符串
const char* charArray = "hello";
std::string str5(charArray);
//使用重复的字符初始化字符串
std::string str6(5,'A');
//输出字符串内容
std::cout<<"str1:"<<str1<<std::endl; //空
std::cout<<"str2:"<<str2<<std::endl; //hello,world!
std::cout<<"str3:"<<str3<<std::endl; //hello,world!
std::cout<<"str4:"<<str4<<std::endl; //hello
std::cout<<"str5:"<<str5<<std::endl; //hello
std::cout<<"str6:"<<str6<<std::endl; //AAAAA
}
03.各种基本操作
- 在C++中,std::string类提供了一个成员函数c_str(),用于返回一个指向以空字符结尾的C风格字符串(即const char*类型)。在进行printf输出时,需要将string转换为C风格的字符串进行输出。
#include <bits/stdc++.h>
using nmaespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
char buf[100]; //存放零时变量,用于输出
scanf("%s",buf); //输入buff
string str(buf); //使用buff来构造str
printf("str = %s\n",str.c_str()); //输出str
}
- 获取字符串长度(length/size)
string str = "hello,world";
int length = str.length(); // 或者int length = str.size();
cout<<"length:"<<length<<endl;
- 字符串查找(find)
string str = "hello,world";
size_t pos = str.find("world"); //查找子字符串的位置
if(pos != string::npos){
cout<<"Substring found at position:"<<pos<<endl;
}else{
cout<<"Substring not found"<<endl;
}
- 拼接字符串(+ 或者 append)
string str = "hello";
string str1 = "world";
string result1 = str +", "str1; //使用 + 号拼接
string result2 = str.append(", ").append(str1); //使用append()函数拼接
- 字符串替换(replace)
string str1 = "hello,world!";
str1.replace(7,5,"Universe"); //替换字符串,7 起始位置,5 字符长度
cout<<"result:"<<str1<<endl; //hello,Universe!
- 提取子字符串(substr)
string str1 = "hello,world!";
string subStr = str1.substr(7,5); //提取字符串,7 起始位置。5 提取个数,注意:不要越界
cout<<"Substring:"<<subStr<<endl;
- 字符串比较(compare)
string重载了不等号,所以可以直接用s1<s2的方式来比较string的大小,比较的规则是按照字典序大小进行比较。
字典序的比较方法是从小到大一个一个比较,一旦遇到不相等的字符就确定大小关系。
string str1 = "hello";
string str2 = "world";
int result = str1.compare(str2); //比较字符串
if(result == 0){
cout<<"String are equal."<<endl;
}else if(result < 0){
cout<<"String 1 is less than String 2"<<endl;
}else{
cout<<"String 1 is greater than String 2"<<endl;
}
- 遍历
常用的遍历方法有两种:
1)循环枚举下标
2)auto枚举(其中&表示取引用类型,如果对i 修改将会改变原来的值)
string s = "hello";
for (int i = 0;i<s.length();++i)cout<<s[i];
cout<<'\n';
for(auto i : s){
cout<<i;
i = 'a'; //此处修改无效,因为这里的i是拷贝出来的,而不是引用s里面的。
}
cout<<'\n';
//此时s = hello;
for(auto &i : s){
cout<<i;
i ='a'; //此处修改s的值
}
cout<<'\n';
//此时s = aaaaa;
cout<<s<<'\n';
04.例题
实现字符数组的反转功能
#include <bits/stdc++.h>
using namespace std;
int main(){
string s;
getline(cin,s);
for(int i=(int)s.length()-1;i>=0;--i){
cout<<s[i];}
return 0;
} //将字符逆序输出,原字符不变
int main(){
string s;
getline(cin,s);
reverse(s.begin(),s.end());
cout<<s<<'\n';
return 0;
} //使用迭代器
int main(){
string s;
getline(cin,s);
for(int i=0;i<s.length()/2;++i)swap(s[i],s[s.length()-i-1]);
cout<<s<<'\n';
return 0;
} //利用下标置换