cpp 05 Lambda 表达式 | std::function | STL 算法 |整数向上取整
·
1. 范围 for 循环(简化容器遍历)
核心要点
- 定义:C++11 引入的简化遍历语法,适用于数组、vector、string 等可迭代容器。
- 语法:
for (元素类型 变量名 : 可迭代对象) { 循环体 } - 关键用法:
- 普通遍历:
for (int p : piles)(只读元素); - 修改元素:
for (int& p : piles) p++(需用引用); - 常量容器遍历:
for (int p : const vector<int>& piles)(不允许修改)。
- 普通遍历:
- 优势:比传统 for 循环简洁,可读性高,编译后效率一致。
学习链接
实战示例(对比传统 for 循环)
vector<int> piles = {3,6,7,11};
// 传统 for 循环
for (int i=0; i<piles.size(); i++) {
cout << piles[i] << " ";
}
// 范围 for 循环(等价)
for (int p : piles) {
cout << p << " ";
}
2. 引用传递(高效传递大容器)
核心要点
- 定义:传递变量的地址而非拷贝,避免大容器(如 1e4 元素的 vector)拷贝的内存浪费和性能损耗。
- 语法:
函数参数类型& 变量名(如void func(vector<int>& nums))。 - 关键用法:
- 普通引用:可修改原变量,用于需要修改参数的场景;
- 常量引用:
const vector<int>& nums,不允许修改原变量,更安全,适用于只读场景(如算法题中的输入数组)。
- 注意:避免悬垂引用(引用已销毁的变量)。
学习链接
- 菜鸟教程:https://www.runoob.com/cplusplus/cpp-references.html
- C++ 官方文档:https://en.cppreference.com/w/cpp/language/reference
实战示例(算法题参数传递)
// 常量引用传递(只读,高效)
bool isValid(const vector<int>& piles, int k, int h) {
long long time = 0;
for (int p : piles) {
time += (p + k - 1) / k;
if (time > h) return false;
}
return true;
}
3. Lambda 表达式(匿名函数,回调常用)
核心要点
- 定义:C++11 引入的匿名函数,可临时定义短小逻辑,无需单独声明 / 定义,适合作为算法回调函数。
- 完整语法:
[捕获列表] (参数列表) -> 返回值类型 { 函数体 } - 关键用法:
- 捕获列表:
[&](按引用捕获所有外部变量)、[=](按值捕获)、[&a, b](指定变量捕获); - 简化写法:无参数时可省略参数列表,返回值可自动推导(如二分搜索中的判断逻辑);
- 算法题场景:常用于二分搜索的条件判断、sort 函数的自定义排序规则。
- 捕获列表:
学习链接
实战示例(二分搜索判断逻辑)
// 二分搜索中用 Lambda 替代独立函数
int minEatingSpeed(vector<int>& piles, int h) {
int left = 1;
int max_pile = *max_element(piles.begin(), piles.end());
int right = max_pile + 1;
while (left < right) {
int mid = left + (right - left) / 2;
// Lambda 表达式([&]捕获外部变量 piles、h)
auto isValid = [&](int k) {
long long time = 0;
for (int p : piles) {
time += (p + k - 1) / k;
if (time > h) return false;
}
return true;
};
if (isValid(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
4. std::function 函数对象(Lambda 容器)
核心要点
- 定义:C++11 提供的通用函数包装器,可存储 Lambda 表达式、函数指针、成员函数等。
- 语法:
std::function<返回值类型(参数类型1, 参数类型2, ...)>(需包含<functional>头文件)。 - 关键用法:
- 存储 Lambda 表达式,解决 Lambda 无法直接作为函数返回值 / 参数传递的问题;
- 封装通用算法模板(如通用二分搜索模板),提高代码复用性。
学习链接
- 菜鸟教程:C++ 标准库 <functional> | 菜鸟教程
- C++ 官方文档:https://en.cppreference.com/w/cpp/utility/functional/function
实战示例(通用二分搜索模板)
#include <functional>
// 通用左闭右开二分搜索模板(接收 function 作为条件)
int binarySearchLeft(int left, int right, function<bool(int)> condition) {
while (left < right) {
int mid = left + (right - left) / 2;
if (condition(mid)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
// 调用模板解决珂珂吃香蕉问题
int minEatingSpeed(vector<int>& piles, int h) {
int left = 1;
int max_pile = *max_element(piles.begin(), piles.end());
int right = max_pile + 1;
// 用 function 封装 Lambda
function<bool(int)> isValid = [&](int k) {
long long time = 0;
for (int p : piles) {
time += (p + k - 1) / k;
if (time > h) return false;
}
return true;
};
return binarySearchLeft(left, right, isValid);
}
5. STL 算法 std::max_element(找容器最大值)
核心要点
- 定义:STL 算法库(
<algorithm>头文件)中的函数,用于查找容器中的最大值。 - 语法:
std::max_element(容器.begin(), 容器.end()),返回指向最大值的迭代器(类似指针)。 - 关键用法:需通过解引用操作(
*)获取最大值;比手动遍历找最大值更简洁高效。
学习链接
- 菜鸟教程:C++ 算法库 <algorithm> | 菜鸟教程
- C++ 官方文档:https://en.cppreference.com/w/cpp/algorithm/max_element
实战示例(二分搜索上界初始化)
vector<int> piles = {3,6,7,11};
// 用 std::max_element 找最大值(简洁)
int max_pile = *max_element(piles.begin(), piles.end());
// 二分搜索右边界(左闭右开)
int right = max_pile + 1;
6. 整数向上取整技巧(避免浮点数精度问题)
核心要点
- 定义:算法题中常用的整数向上取整方法,替代浮点数
ceil()函数,避免精度误差和溢出。 - 核心公式:
(a + b - 1) / b(a、b 为正整数),等价于ceil(a / b)。 - 原理:通过调整分子,让整数除法自动实现向上取整(如
a=7, b=4→(7+4-1)/4=2)。 - 适用场景:时间计算、分组问题、资源分配等需要向上取整的场景(如珂珂吃香蕉中每堆香蕉的耗时计算)。
学习链接
- 知乎(推导过程):https://zhuanlan.zhihu.com/p/361845021
- 博客园(技巧总结):https://www.cnblogs.com/huashanqingzhu/p/11040390.html
实战示例(每堆香蕉耗时计算)
int pile = 7; // 某堆香蕉数量
int speed = 4; // 吃香蕉速度
// 整数向上取整(推荐)
int time = (pile + speed - 1) / speed; // 结果为 2
// 浮点数方法(可能有精度问题)
int time2 = ceil(pile / (double)speed); // 结果为 2
更多推荐


所有评论(0)