一、查找算法(Binary Search)
1. STL 内置二分查找函数(适用于有序容器)
#include<iostream>#include<algorithm>#include<vector>using namespace std;intmain(){vector<int> arr = {1, 2, 3, 3, 3, 5, 7};// 1. 判断元素是否存在bool exists = binary_search(arr.begin(), arr.end(), 3); // true// 2. 查找第一个 >= 3 的位置(指向第一个3)auto it1 = lower_bound(arr.begin(), arr.end(), 3);cout << "第一个>=3的索引: " << it1 - arr.begin() << endl; // 输出 2// 3. 查找第一个 > 3 的位置(指向5)auto it2 = upper_bound(arr.begin(), arr.end(), 3);cout << "第一个>3的索引: " << it2 - arr.begin() << endl; // 输出 5// 4. 统计值为3的元素个数int count = upper_bound(arr.begin(), arr.end(), 3) - lower_bound(arr.begin(), arr.end(), 3);cout << "3的个数: " << count << endl; // 输出 3// 5. equal_range 一次性获取区间 返回值为pair<iterator,iterator>auto range = equal_range(arr.begin(), arr.end(), 3);cout << "3的范围: [" << (range.first - arr.begin())<< ", " << (range.second - arr.begin()) << ")" << endl; // 输出 [2, 5)return 0;}
手写二分查找模板(最常用,灵活度高)
场景一:在有序数组中查找目标值(标准模板)
intbinarySearch(vector<int>& arr, int target){int left = 0, right = arr.size() - 1;while (left <= right) {int mid = left + (right - left) / 2; // 防止溢出if (arr[mid] == target) return mid;else if (arr[mid] < target) left = mid + 1;else right = mid - 1;}return -1; // 未找到}
场景二:查找第一个满足条件的元素(左边界,即 lower_bound 手写版)
intlowerBound(vector<int>& arr, int target){int left = 0, right = arr.size(); // 注意右边界是开区间while (left < right) {int mid = left + (right - left) / 2;if (arr[mid] >= target) right = mid; // 满足条件,向左收缩else left = mid + 1; // 不满足,向右收缩}return left; // 返回第一个 >= target 的索引}
场景三:查找最后一个满足条件的元素(右边界,即 upper_bound - 1 手写版)
intupperBound(vector<int>& arr, int target){int left = 0, right = arr.size();while (left < right) {int mid = left + (right - left) / 2;if (arr[mid] > target) right = mid; // 满足 > 条件,向左收缩else left = mid + 1; // 不满足(<= target),向右收缩}return left - 1; // 返回最后一个 <= target 的索引}
二分查找在答案值上的应用(二分答案)
boolcheck(int mid) {// 根据 mid 判断是否满足题目条件// 返回 true 表示 mid 可行,false 表示不可行}intsolve() {int left = 0, right = 1e9; // 根据题目设定上下界int ans = -1;while (left <= right) {int mid = left + (right - left) / 2;if (check(mid)) {ans = mid; // 记录可行解left = mid + 1; // 尝试更大的值(求最大可行解)// 若求最小可行解,则 right = mid - 1;} else {right = mid - 1; // mid 不可行,收缩右边界}}return ans;}
注意事项
二、排列函数(全排列)
1. 排列函数基本用法示例
vector<int> nums = {1, 2, 3};// next_permutation 示例next_permutation(nums.begin(), nums.end()); // nums 变为 {1, 3, 2}// 遍历全部排列(从升序开始)sort(nums.begin(), nums.end());do {// 处理当前排列} while (next_permutation(nums.begin(), nums.end()));// 输出顺序:123, 132, 213, 231, 312, 321// prev_permutation 示例vector<int> nums2 = {1, 3, 2};prev_permutation(nums2.begin(), nums2.end()); // nums2 变为 {1, 2, 3}// 遍历全部排列(从降序开始)sort(nums2.begin(), nums2.end(), greater<int>());do {// 处理当前排列} while (prev_permutation(nums2.begin(), nums2.end()));// 输出顺序:321, 312, 231, 213, 132, 123
2. 排列函数进阶用法
struct Person { string name; int age; };boolcmp(const Person& a, const Person& b) { return a.age < b.age; }sort(people.begin(), people.end(), cmp);do {/* 处理排列 */} while (next_permutation(people.begin(), people.end(), cmp));
三、树形结构
1. 二叉树节点定义
struct TreeNode {int val;TreeNode* left;TreeNode* right;TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}};
2. 二叉树的递归遍历
// 先序遍历(根→左→右)void preorder(TreeNode* root) {if (!root) return;cout << root->val;preorder(root->left);preorder(root->right);}// 中序遍历(左→根→右)void inorder(TreeNode* root) {if (!root) return;inorder(root->left);cout << root->val;inorder(root->right);}// 后序遍历(左→右→根)void postorder(TreeNode* root) {if (!root) return;postorder(root->left);postorder(root->right);cout << root->val;}
四、优先队列(堆 priority_queue)
// priority_queue 模版类,用于实现优先队列 默认为大根堆// 最大堆(默认)priority_queue<int> max_heap;// 最小堆// vector<int> 为默认容器 greater<int> 为默认比较函数priority_queue<int, vector<int>, greater<int>> min_heap;// 自定义比较函数struct cmp {booloperator()(int a, int b){// 重载运算符,用于比较两个元素的优先级return a > b; // 注意:返回true表示优先级低}};priority_queue<int, vector<int>, cmp> custom_heap;
觉得有用的话,一键三连支持一下吧~
夜雨聆风