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,不允许修改原变量,更安全,适用于只读场景(如算法题中的输入数组)。
  • 注意:避免悬垂引用(引用已销毁的变量)。
学习链接
实战示例(算法题参数传递)
// 常量引用传递(只读,高效)
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 无法直接作为函数返回值 / 参数传递的问题;
    • 封装通用算法模板(如通用二分搜索模板),提高代码复用性。
学习链接
实战示例(通用二分搜索模板)
#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()),返回指向最大值的迭代器(类似指针)。
  • 关键用法:需通过解引用操作(*)获取最大值;比手动遍历找最大值更简洁高效。
学习链接
实战示例(二分搜索上界初始化)
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)。
  • 适用场景:时间计算、分组问题、资源分配等需要向上取整的场景(如珂珂吃香蕉中每堆香蕉的耗时计算)。
学习链接
实战示例(每堆香蕉耗时计算)
int pile = 7; // 某堆香蕉数量
int speed = 4; // 吃香蕉速度
// 整数向上取整(推荐)
int time = (pile + speed - 1) / speed; // 结果为 2
// 浮点数方法(可能有精度问题)
int time2 = ceil(pile / (double)speed); // 结果为 2

更多推荐