别再背STL语法了!用这5个高频场景代码片段,搞定C++刷题和项目
别再背STL语法了用这5个高频场景代码片段搞定C刷题和项目每次打开LeetCode准备刷题或是开始一个新项目时你是不是总要先翻出那本厚厚的STL手册然后花半小时回忆vector怎么删除元素、map如何统计频率其实真正高效的开发者手里都有一套经过实战检验的代码模板。下面这5个高频场景的解决方案能覆盖80%的算法题和项目需求。1. 高效删除vector中的特定元素新手常犯的错误是直接遍历删除// 错误示范 for(int i0; ivec.size(); i){ if(vec[i] target) { vec.erase(vec.begin()i); } }这会导致迭代器失效和漏删问题。正确的O(n)时间复杂度做法是vectorint vec {1,3,5,7,3,9}; int target 3; // 正确写法 vec.erase( remove(vec.begin(), vec.end(), target), vec.end() ); // 或者使用迭代器版本适用于复杂条件 for(auto itvec.begin(); it!vec.end();){ if(*it % 2 0){ // 删除所有偶数 it vec.erase(it); } else { it; } }提示remove算法实际上是把要保留的元素前移返回新的逻辑终点需要配合erase完成物理删除2. 统计元素频率的三种姿势根据数据特点选择最优方案场景容器选择时间复杂度代码复杂度数据范围已知且较小数组O(n)★☆☆需要排序遍历mapO(nlogn)★★☆只需快速查询unordered_mapO(n)★★☆// 方案1数组计数适合元素值较小的情况 vectorint nums {1,3,2,1,5,2}; int count[100] {0}; // 假设元素不超过100 for(int num : nums) count[num]; // 方案2map自动排序需要有序输出时 mapstring, int wordCount; for(auto word : words){ wordCount[word]; // 等价于 // auto it wordCount.find(word); // if(it ! wordCount.end()) it-second; // else wordCount.insert({word,1}); } // 方案3哈希表最快查询 unordered_mapchar, int freq; for(char c : s) freq[c];3. Top K问题的优先队列解法求前K大/小元素时维护一个大小为K的堆是关键// 前K大元素维护小顶堆 vectorint topKFrequent(vectorint nums, int k) { unordered_mapint,int freq; for(int num : nums) freq[num]; // 定义小顶堆比较函数 auto cmp [](pairint,int a, pairint,int b){ return a.second b.second; }; priority_queuepairint,int, vectorpairint,int, decltype(cmp) pq(cmp); for(auto [num, count] : freq){ pq.push({num, count}); if(pq.size() k) pq.pop(); } vectorint res; while(!pq.empty()){ res.push_back(pq.top().first); pq.pop(); } return res; }注意求前K大用小顶堆淘汰小的求前K小用大顶堆淘汰大的4. 字符串处理的四件套字符串问题90%逃不过这四种操作分割getlinestringstream组合string s apple,banana,orange; stringstream ss(s); string token; while(getline(ss, token, ,)){ cout token endl; }匹配KMP算法模板适合重复匹配vectorint buildNext(string pattern){ vectorint next(pattern.size()); for(int i1, j0; ipattern.size(); i){ while(j0 pattern[i]!pattern[j]) j next[j-1]; if(pattern[i] pattern[j]) j; next[i] j; } return next; }转换transformlambda表达式string s Hello123; // 转大写 transform(s.begin(), s.end(), s.begin(), [](char c){ return toupper(c); }); // 过滤非字母 s.erase(remove_if(s.begin(), s.end(), [](char c){ return !isalpha(c); }), s.end());解析正则表达式#include regex string log Error: 404 Not Found; smatch matches; if(regex_search(log, matches, regex(Error: (\\d)))){ cout 错误代码: matches[1] endl; }5. 自定义排序的六种写法STL排序的灵活用法能大幅减少代码量vectorvectorint intervals; vectorpairint, string products; // 1. Lambda表达式最常用 sort(intervals.begin(), intervals.end(), [](auto a, auto b){ return a[1] b[1]; }); // 2. 预定义比较函数 bool cmp(pairint,string a, pairint,string b){ if(a.first ! b.first) return a.first b.first; return a.second b.second; } sort(products.begin(), products.end(), cmp); // 3. 重载运算符适合自定义类型 struct Task{ int priority; string name; bool operator(const Task other) const { return priority other.priority; // 降序 } }; // 4. 使用函数对象 struct CompareByLength{ bool operator()(const string a, const string b){ return a.size() b.size(); } }; vectorstring words; sort(words.begin(), words.end(), CompareByLength()); // 5. 多条件排序tuple自动比较 vectortupleint,int,string records; sort(records.begin(), records.end()); // 自动按元组顺序比较 // 6. 逆序排序简便写法 sort(nums.rbegin(), nums.rend());实战技巧容器选择的黄金法则遇到问题时按照这个决策树选择容器是否需要快速查找是 → 选择unordered_set/mapO(1)否 → 进入2是否需要自动排序是 → 选择set/mapO(logn)否 → 进入3是否需要随机访问是 →vector或deque否 → 进入4是否先进先出是 →queue否 →stack特殊场景需要维护极值priority_queue需要双向操作deque需要去重排序set字符串处理stringregex把这些代码片段保存到你的代码库中下次遇到类似问题时直接调用。记住优秀的开发者不是记住所有API而是知道如何快速找到最适合的解决方案。