leetcode
leetcode
//to_string()//数字转字符串 //stoi()字符串转数字 //string(1,char)字符转数字//string构造函数
1LL会在运算时把后面的临时数据扩容成long long类型,再在赋值给左边时转回int类型。
array<int, 26>
array:这是 C++ 标准库中的一个模板类,位于
unordered_map
在C++中,std::unordered_map 是一个关联容器,用于存储键值对(key-value pairs)。如果你想检查 std::unordered_map 是否包含某个键(key),可以使用 find() 方法或 count() 方法。虽然 C++20 引入了 contains() 方法,但如果你使用的是 C++20 之前的版本,就需要用其他方式来实现。 使用 find() 方法 find() 方法会在容器中查找指定的键。如果找到了,返回一个指向该键值对的迭代器;如果没有找到,返回 end() 迭代器。
2.使用 count() 方法 count() 方法会返回键在容器中出现的次数(对于 unordered_map,只能是 0 或 1)
3.使用 C++20 的 contains() 方法 如果你使用的是 C++20 或更高版本,可以直接使用 contains() 方法。它会返回一个布尔值,表示容器是否包含指定的键。 // 注意不要直接 += cnt[sj-k],如果 sj-k 不存在,会插入 sj-k
static constexpr int directions[4][2] = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
这种定义通常用于二维平面的搜索问题,如迷宫搜索、棋盘游戏、网格路径搜索等。 通过遍历这个数组,可以方便地实现从当前位置向四个方向的移动。 constexpr 的作用: constexpr 表示这个数组是一个编译时常量,它的值在编译时就已经确定,不能在运行时修改。 这样可以提高代码的效率和安全性,同时避免在运行时动态分配内存。 constexpr 是 C++11 引入的一个非常强大的关键字,它的作用是声明一个“编译时常量表达式”,即在编译阶段就能确定其值的变量或函数。使用 constexpr 可以显著提高代码的效率和安全性,同时还能让代码更加清晰和易于维护。 具体用法略
lambada表达式
这段代码是一个使用C++17标准的lambda表达式,并且使用了递归和参数化捕获的特性 [&]表示捕获当前作用域中的所有变量 this auto&& dfs:这是C++17中引入的参数化捕获特性。this auto&&表示捕获当前lambda对象的引用,允许lambda在递归调用时引用自身。 -> void:表示这个lambda表达式没有返回值 auto dfs = [&](this auto&& dfs, int i) -> void { if (i == nums.size()) { ans++; return; } }; Lambda 表达式是一种强大的工具,它结合了简洁性、匿名性、闭包特性以及与 STL 算法的无缝集成。它在现代 C++ 编程中被广泛应用,尤其是在需要定义简单函数、捕获上下文或实现递归时。
- 简洁性
- 捕获上下文 Lambda 表达式可以捕获外部变量(通过 [&] 或 [=]),这使得它能够直接访问和修改外部作用域的变量,而无需通过参数传递。
- 匿名性
- 支持闭包 Lambda 表达式本质上是一种闭包,它可以捕获外部变量并将其封装起来。这使得 Lambda 表达式可以作为函数对象(functor)使用,而无需显式定义类。 5.支持递归 从 C++17 开始,Lambda 表达式可以通过 this auto&& 捕获自身,从而实现递归调用。这使得 Lambda 表达式可以用于复杂算法(如深度优先搜索、动态规划等) 6.与 STL 算法结合 Lambda 表达式与 C++ 标准库中的算法(如 std::sort、std::for_each、std::transform 等)结合得非常好,可以实现非常简洁的代码。
- 减少代码冗余 在某些场景下,使用 Lambda 表达式可以避免定义多个小函数,从而减少代码冗余。例如,在多线程编程中,Lambda 表达式可以直接捕获线程需要的上下文。
emplace_back
contains
在C++中,std::unordered_set 是一个关联容器,用于存储唯一的元素。从C++20开始,std::unordered_set 提供了一个成员函数 contains,用于检查容器中是否包含某个元素。这是一个非常方便的函数,可以替代之前的 find 或 count 方法。
std::unordered_set::contains 的用法
函数原型 cpp复制
bool contains(const key_type& key) const; 参数:key 是要检查的元素。 返回值:如果容器中包含该元素,则返回 true;否则返回 false。
lower_bound(nums.begin(),nums.end(),target);
lower_bound() 是 C++ 标准库中的一个函数,它在有序容器(如 std::vector、std::array、std::deque 等)中查找不小于给定值的第一个元素。这个函数使用二分查找算法,因此它的查找效率是 O(log n)。
memset
它定义在
常见用途:
初始化内存区域 清空内存
sizeof
sizeof 是 C++ 中的一个运算符,用于获取变量、类型或表达式的大小(以字节为单位)。它是一个编译时运算符,因此它的结果在编译时就已经确定,不会在运行时计算。
函数的声明如下:
Vector
1.assign assign 用于重新分配容器的内容,会清空当前容器,并用新的内容填充。
2.resize resize 用于调整容器的大小,同时可以指定新元素的默认值。
3.reverse reverse 并不是 std::vector 的成员函数,而是 C++ 标准库中的一个算法,用于反转容器中的元素顺序。
4.reserve reserve 用于预留容器的内存空间,但不会改变容器的大小
max_element
在 C++ 中,max_element 是标准模板库(STL)中的一个算法函数,定义在头文件
reduce
std::reduce 是C++17中引入的一个算法,它位于
在代码中,dfs 函数的参数 const string& s 使用了引用传参,这是出于性能优化和语义清晰的考虑。以下是详细解释:
- 性能优化:避免不必要的拷贝 在C++中,传递大型对象(如字符串、向量等)时,直接传递会触发拷贝构造函数,导致对象被复制一份。对于字符串 s,如果直接传递,每次递归调用都会复制整个字符串,这会带来不必要的开销,尤其是在字符串较长时。
例如: void dfs(string s, int i); // 直接传递 每次调用 dfs 时,都会复制整个字符串 s,这会导致时间复杂度和空间复杂度显著增加。
而使用引用传参: void dfs(const string& s, int i); // 引用传参 这种方式不会复制字符串,而是直接传递原始字符串的引用。这样可以显著减少内存占用和拷贝时间,提高程序的运行效率。
- 语义清晰:明确字符串不会被修改 在 dfs 函数中,字符串 s 是输入参数,且在递归过程中不需要修改它。使用 const string& 表示: 只读访问:const 修饰符表明 s 在函数内部不会被修改,这有助于代码的可读性和安全性。 明确意图:引用传参表明 s 是一个共享的输入数据,而不是每次递归调用时的独立副本。
这种写法清晰地表达了函数的语义:dfs 函数只是对输入字符串 s 进行读取操作,而不会修改它。
- 对比:直接传递 vs 引用传递 假设字符串 s 的长度为 n,递归深度为 n: 直接传递:每次递归调用都会复制整个字符串,总的时间复杂度为 O(n^2),空间复杂度也为 O(n^2)。 引用传递:每次递归调用只是传递一个引用,时间复杂度为 O(n),空间复杂度为 O(n)(主要来自递归栈)。
因此,使用引用传参可以显著优化性能,尤其是在处理大字符串时。
- 总结 在 dfs 函数中,使用 const string& s 的原因如下: 性能优化:避免不必要的字符串拷贝,减少时间和空间开销。 语义清晰:明确字符串是只读的输入参数,不会被修改。 最佳实践:在C++中,对于大型对象(如字符串、向量等),通常推荐使用引用传参,以提高效率。
这种写法是C++编程中的常见优化技巧,尤其适用于递归函数和深度优先搜索场景。
perror函数
perror 是一个在 C 语言中常用的函数,用于打印错误信息。它属于标准库 <stdio.h>,主要用于将错误信息输出到标准错误输出(通常是屏幕)。 void perror(const char *s); perror 常用于处理系统调用或库函数失败时的错误。当这些函数失败时,它们通常会将错误码存储在 errno 中,而 perror 可以帮助开发者快速定位问题。
typdef函数
C语言允许用户使用 typedef 关键字来定义自己习惯的数据类型名称,来替代系统默认的基本类型名称、数组类型名称、指针类型名称与用户自定义的结构型名称、共用型名称、枚举型名称等
为基本数据类型定义新的类型名
为自定义数据类型(结构体、共用体和枚举类型)定义简洁的类型名称
typedef struct tagNode { char *pItem; pNode pNext; } *pNode; 其实问题并非在于 struct 定义的本身,大家应该都知道,C 语言是允许在结构中包含指向它自己的指针的,我们可以在建立链表等数据结构的实现上看到很多这类例子。那问题在哪里呢?其实,根本问题还是在于 typedef 的应用。
在上面的代码中,新结构建立的过程中遇到了 pNext 声明,其类型是 pNode。这里要特别注意的是,pNode 表示的是该结构体的新别名。于是问题出现了,在结构体类型本身还没有建立完成的时候,编译器根本就不认识 pNode,因为这个结构体类型的新别名还不存在,所以自然就会报错。因此,我们要做一些适当的调整,比如将结构体中的 pNext 声明修改成如下方式: 解决办法 1.在struct前加typdef 2.将struct与typdef分开定义
为数组定义简洁的类型名称
为指针定义简洁的名称
typedef 是用来定义一种类型的新别名的,它不同于宏,不是简单的字符串替换
assert函数
assert 是 C 语言中一个非常有用的调试工具,用于在程序运行时检查条件是否为真。如果条件为假(即表达式的结果为 0),程序会终止运行,并打印一条错误信息,指出断言失败的位置。
C语言和C++的最大数据结构和最小数据结构
头文件都问 <limits.h> C语言最大数据结构 INT_MAX C语言最小数据结构 INT_MIN C++语言最大数据结构 INT32_MAX C++语言最小数据结构 INT32_MIN
uint64_t
是一种数据类型,通常用于表示无符号的64位整数
定义
它是C语言和C++语言中定义的一种标准整数类型。
在C语言中,uint64_t 是通过头文件 <stdint.h> 定义的。
在C++语言中,uint64_t 是通过头文件
特点
无符号:uint64_t 是无符号整数类型,这意味着它不能表示负数,只能表示非负整数。 64位:uint64_t 占用64位(8字节)的存储空间,因此它可以表示的数值范围是从0到 264−1,即从0到18446744073709551615。 平台无关性:uint64_t 是一种固定宽度的整数类型,它的大小在所有支持它的平台上都是固定的,不会因平台的不同而改变。
使用场景
大整数计算:当需要处理较大的整数时,uint64_t 是一个合适的选择。例如,在处理大文件的偏移量、大数组的索引或者大范围的计数器时,uint64_t 可以提供足够的存储空间。 跨平台开发:在跨平台的程序中,使用 uint64_t 可以确保整数的大小在不同的平台上保持一致,避免因平台差异导致的错误。 性能优化:在某些情况下,使用 uint64_t 可以提高程序的性能。例如,在进行位运算或整数运算时,64位整数的运算速度可能会比32位整数更快。
点赞数据加载中