[C/C++]-语法复习&秋招刷题记录
记录一些刷算法题中的常用C++语法和经典题型,作为复习和梳理。
上一篇踩坑记录:https://www.cnblogs.com/camilia/p/15743180.html
刷题目录和参考资料:代码随想录
STL相关
数据类型转换
vector<int>(ans.begin(),ans.end())
TODO 补充说明
Vector
初始化
头文件:#include <vector>
初始化:vector <数据类型> 变量名 (长度,初始化值)
赋值初始化:vector <数据类型> 变量名 = {1,2,3,4,5}
可以作为数组
数组开头:array.begin()
数组结尾:array.end()
数组大小:array.size()
增删
添加元素到尾部:array.push_back(x)
删除元素:
函数传参引用
vector<int>& array
Set
初始化
无序set初始化:unordered_set<int> s;
有序不重复:set
有序可重复:multiset
std::unordered_set底层实现为哈希表,std::set 和std::multiset 的底层实现是红黑树,红黑树是一种平衡二叉搜索树,所以key值是有序的,但key不可以修改,改动key值会导致整棵树的错乱,所以只能删除和增加
常见用法
- 哈希表:快速判断一个元素是否出现集合里的时候,可以考虑哈希表,空间换时间。
- 自动排序
-
拥有去重的特性,增
insert()
、删erase()
、查find()
复杂度与哈希表相同,均为O(1)。 -
优先使用unordered_set,因为它的查询和增删效率是最优的。拥有去重的特性,增
insert()
、删erase()
、查find()
复杂度与哈希表相同,均为O(1)。 -
如果需要集合是有序的,那么就用set,如果要求不仅有序还要有重复数据的话,那么就用multiset。
Map
与set类似:
在map 是一个key value 的数据结构,map中,对key是有限制,对value没有限制的,因为key的存储方式使用红黑树实现的。
常见用法
- 哈希表:a中查找key不为空的条件
a.count(key) > 0
- 计数器:
unordered_map<int, int> count
x计数:count[x]++;
。
string
输入
可以用getline读取一行,读取到换行符'\n'时会结束返回。
输入的字符串内有空格:getline(cin, s)
,可以保留空格,s的数据类型是string;
加入参数,可以设置成停止符:getline(cin, s, ',')
,读取输入到','截止。
也可以把读入的输入字符串,转换成stringstream,再进行处理。
#include<sstream>
string line;
getline(cin, line);
stringstream ss(line);
while(getline(line, s, ',')){} //此时一行有多个字符串输入,中间用逗号隔开
获取长度
s.length()
指定位置子串
string substr = s.substr(start, num); //从index为start开始的num个字符。
删除指定字符
string substr = s.erase(s.begin() + j); //删除index=j的字符
进制转换
int num1 = stoi(str, 0, 2); //将字符串 str 从 0 位置之后的数字的 2 进制数,转换为十进制。参数分别为:被转换字符串、开始转换位置、原数制
int num2 = atoi(s.c_str());// atoi把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。要先转化为const char*,默认转换都是十进制
字符转换
数字转换成字符串:
int num = 123456789;
string s = to_string(num);//s="123456789"
数据结构相关
链表
初始化
用结构体定义
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
用默认模板定义
# 定义同时赋值
ListNode* head = new ListNode(5); //头节点,值为5。
# 定义完再赋值
ListNode* head = new ListNode();
head->val = 5;
删除元素
用C++写链表删除某个元素时要记得将删掉的元素释放内存。
//以头结点为例
ListNode* temp = head;
head = head->next;
delete temp;
链表 VS. 数组
C++语法相关
输入输出
遇到不定长输入时,可以用cin.get()读取换行符:
if(cin.get() == '\n'){
//此时说明一行输入结束
}
注意!getline(cin,x)
取输入时,取到换行符截止,所以在下一次读取时,需要把cin中剩下的换行符拿走。可以用cin.get()
取一个字符,在程序末尾也可以用cin.ignore(100, '\n')
。
循环遍历
for (int i: arrays)
i作为下标使用,类型int
是arrays内的数据类型
for(auto & x : arrays)
x是arrays的遍历值arrays[index]
不是下标
指针
nullptr
用以解决NULL在隐式转换和作为函数传入参数时的二义性问题。
C和C++在处理void 类型的时候存在一定的区别。C语言中,void类型的变量可以赋值给任意类型的指针,也可以被任意类型的指针赋值,两个方向都不会报错。但是C++具有更严格的类型检查,前者是不被允许的。
参考:https://www.jianshu.com/p/09e3b40929ad
所以在初始化和判断空指针时最好使用nullptr
。
malloc
malloc函数返回值的类型是 void*
,C不要求强制类型转换,会自动进行隐式转换,但是C++则需要,因为void*
不能转换成其他类型的指针。
int len = 100;
int p = malloc(len * sizeof(int)); // C推荐做法
int p = (int )malloc(len * sizeof(int)); // C++推荐做法
常见考题
数组
二分查找
时间复杂度:O(n)->O(logn)
边界条件:
- 结束查找的条件
- 移动左右区间
依据:
- 查找空间是闭区间还是开区间
快慢指针
通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
时间复杂度: O(n^2)->O(n)
典型应用: 移除某个元素。
注意:数组在内存中是连续的地址空间。
滑动窗口
根据当前子序列和大小的情况,不断调节子序列的起始位置。
时间复杂度: O(n^2)->O(n)
边界条件:
- 右指针移动直至窗口满足条件1
- 左指针移动直至窗口满足条件2
典型应用: 查找子序列。
循环模拟
注意边界条件。
链表
虚头结点
遇到头结点需要单独处理的情况,例如删除某个节点,用虚头结点作为起始比较方便。
双指针法
遍历链表时经常新建一个指针来作为当前遍历的位置。
双指针法可以实现一遍遍历实现两遍遍历的功能,例如反转链表。
快慢指针可以实现特定问题的设置,例如环形链表。
哈希表
哈希表是根据关键码的值而直接进行访问的数据结构(数组)。哈希表中关键码就是数组的索引下标,然后通过下标直接访问数组中的元素。
可以由数组、Set、Map三种数据结构组成,三种方式要根据题目的特点选择:
- 数组的大小是受限制的,如果元素很少,哈希值太大会造成内存空间的浪费。适合key固定而且数量不多的情况。
- Set是一个集合,适合key数量不固定的情况。
- Map有键值,适合除了查询key也要保存key相关的情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律