C++ LeetCode 刷题经验、技巧及踩坑记录【一】
前言
记录一些小技巧以及平时不熟悉的知识。
正文
c++ 计时器
#include <chrono>
using namespace std;
using namespace chrono;
auto start = system_clock::now();
// do something...
auto end = system_clock::now();
auto duration = duration_cast<microseconds>(end - start);
cout << "花费了"
<< double(duration.count()) * microseconds::period::num / microseconds::period::den
<< "秒" << endl;
string 操作效率
string tmp="XXX";
tmp.clear(); 比 tmp=""; 效率高
tmp.push_back("x"); 比 tmp+= "X"; 效率高
引用传递与值传递
for(auto &c:s)与for(auto c:s)的区别
for(auto c:s)中s为一个容器,效果是利用c遍历并获得s容器中的每一个值,但是c无法影响到s容器中的元素。
for(auto &c:s)中加了引用符号,可以对容器中的内容进行赋值,即可通过对c赋值来做到容器s的内容填充。
使用for(auto &c:s)时,直接引用原字符串进行遍历操作。
使用for(auto c:s)时,逻辑上会复制一个s字符串再进行遍历操作。
由于复制一个字符串花费了大量的时间,所以第一种用法的程序执行速度要快于第二种用法。
凡是遇到时间超限,首先检查一下是不是使用了值传递。
vector 快速遍历
遍历vector时,相对于index++ ,直接擦除vector的第一个元素,每次读取0索引位置的元素速度快得多,当然,这只能用于后续不需要这个vector的情况,如 LeetCode297题解。
vector.erase(vector.begin());
vector[0];
效率比
vector[index];
index++;
快得多
同一工程下避免出现同名的类
在使用unordered_map时,在类里最好是通过引用传递,如果使用private私有数据形式,在本地VS2022下运行会报错,但在LeetCode上却能正常运行。如LeetCode652题解
class Solution {
public:
string dfs(TreeNode* root, vector<TreeNode*>& res, unordered_map<string, int>& mp){
if(root==NULL) return "";
//二叉树先序序列化
string str = to_string(root->val) + "," + dfs(root->left, res, mp) + "," + dfs(root->right, res, mp);
if(mp[str]==1){
res.push_back(root);
}
mp[str]++;
return str;
}
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
vector<TreeNode*> res;
unordered_map<string, int> mp;
dfs(root, res, mp);
return res;
}
};
正常运行
class Solution {
private:
vector<TreeNode*> res;
unordered_map<string, int> mp;
public:
string dfs(TreeNode* root, vector<TreeNode*>& res, unordered_map<string, int>& mp){
if(root==NULL) return "";
//二叉树先序序列化
string str = to_string(root->val) + "," + dfs(root->left, res, mp) + "," + dfs(root->right, res, mp);
if(mp[str]==1){
res.push_back(root);
}
mp[str]++;
return str;
}
vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
dfs(root, res, mp);
return res;
}
};
报错
这个奇怪的问题困扰了我很久,目前可以通过该方法解决,但依旧搞不清原因。
终于知道上述报错的原因了
因为我的VS项目里有多个同名类函数(大量的Sulotion类),凡是类里面有 vector 或者 unordered_map 私有变量的,都要避免同名,否则会在类的析构时抛出异常而中断。
中断通常出现在 xmemory 或者 xhash 文件中
位运算>> 取均值
int mid = (l + r) >> 1;
归并排序框架
class Solution_912 {
vector<int> tmp;
void mergeSort(vector<int>& nums, int l, int r) {
if (l >= r) return;
int mid = (l + r) >> 1;
IC(l + r);
IC(mid);
mergeSort(nums, l, mid);
mergeSort(nums, mid + 1, r);
int i = l, j = mid + 1;
int cnt = 0;
while (i <= mid && j <= r) {
if (nums[i] <= nums[j]) {
tmp[cnt++] = nums[i++];
}
else {
tmp[cnt++] = nums[j++];
}
}
// 即j>r,右半数组完成排序
while (i <= mid) {
tmp[cnt++] = nums[i++];
}
//即i>mid,左半数组完成排序
while (j <= r) {
tmp[cnt++] = nums[j++];
}
//将排序好的tmp复制给nums
for (int i = 0; i < r - l + 1; ++i) {
nums[i + l] = tmp[i];
}
}
public:
vector<int> sortArray(vector<int>& nums) {
//给tmp开辟空间,都存0
tmp.resize((int)nums.size(), 0);
mergeSort(nums, 0, (int)nums.size() - 1);
return nums;
}
};
vector执行 resize() 默认初始化
如果使用vector的resize()之前其大小(size()==0)为0,则resize()会给每个初始化;如果之前大小不为0,则之前部分的值不变,后面扩充的空间的值会初始化。
vector<bool> color;
vector<bool> visited;
color.resize(n);
visited.resize(n); //这里默认初始化为0(也就是false)
索引小于0的报错
提交代码运行,出现以下报错则仔细检查索引。
Line 1034: Char 34: runtime error: addition of unsigned offset to 0x602000000150 overflowed to 0x601efafafc48 (stl_vector.h)
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/stl_vector.h:1043:34
并查集框架
/*Union - Find 算法的复杂度可以这样分析:
构造函数初始化数据结构需要 O(N) 的时间和空间复杂度;
连通两个节点 union、判断两个节点的连通性 connected
、计算连通分量 count 所需的时间复杂度均为 O(1)。*/
class UF
{
private:
vector<int>parent;
int count;
public:
UF(int n)
{
/// @brief 初始化
/// @param n
count = n;
for (int i = 0; i < n; i++)
{
parent.push_back(i);
}
}
int find(int x)
{
/// @brief 找根节点
/// @param x
/// @return
if (x != parent[x])
{
parent[x] = find(parent[x]);
}
return parent[x];
}
void unite(int x, int y)
{
/// @brief 连接两个节点
/// @param x
/// @param y
parent[find(x)] = find(y);
count--;
}
bool isConnected(int x, int y)
{
/// @brief 判断两节点是否连接
/// @param x
/// @param y
/// @return
return parent[find(x)] == find(y);
}
};