C++ Vector算法精讲与底层探秘:从经典例题到性能优化全解析

C++ Vector算法精讲与底层探秘:从经典例题到性能优化全解析

前引:在C++标准模板库(STL)中,vector作为动态数组的实现,既是算法题解的基石,也是性能优化的关键战场。其连续内存布局、动态扩容机制和丰富的成员函数,使其在面试高频题(如LeetCode、洛谷)中频繁登场。本文聚焦​六大经典算法场景​(含杨辉三角、去重、结构体排序等),深入解析vector的​底层扩容策略​​、​​迭代器失效陷阱​​及​​内存管理优化技巧​​,结合代码复现与复杂度对比,帮助开发者从“会用”进阶到“用精”

目录

只出现一次的数字I

原理讲解 

代码展示 

杨辉三角

原理讲解 

 代码展示

电话号码字母组合

原理讲解

代码展示

整型去重

原理讲解 

 代码展示

找只出现一次的数字II

原理讲解

代码展示

只出现一次的数字III

​编辑原理讲解

代码展示

 ​编辑


只出现一次的数字I

https://leetcode.cn/problems/single-number  

原理讲解 

 这种题可以通过排序来找,但最高效的是按位异或:^

按位异或原理:比较二进制,相同为0,相异为1,如果两个数字一模一样去异或,那么就可以消除

代码展示 
class Solution { public: int singleNumber(vector<int>& nums) { int tmp=0; for(int i=0;i<nums.size();i++) { tmp^=nums[i]; } return tmp; } };

当然用范围for、迭代器也是可以的,因为也是遍历(支持迭代器就支持范围for)

class Solution { public: int singleNumber(vector<int>& nums) { int tmp=0; //范围for for(auto e:nums) { tmp^=e; } return tmp; } };
class Solution { public: int singleNumber(vector<int>& nums) { int tmp=0; //迭代器 auto it = nums.begin(); while(it!=nums.end()) { tmp ^= (*it); it++; } return tmp; } };

杨辉三角

原理讲解 

(1)第一步

首先两数的计算肯定是没有问题的,对应两个数相加即可,下面我来此题转化一下得到它的本质

从上图看见这是一个二维数组,每行的元素个数都不同,我们可以采用vector来开辟一个二维数组,下面我们来看如何开辟:vector<vector<int>>vector这是二维数组类型,为何 int 不用 int*?

外面的vector表示开辟了一定数量的类型元素,比如:vector<vector<int>> 5,表示5个vector<int>

而里面的每个vector<int>又是一个类型,这样我们可以先访问外面的->里面的,达到二维数组

如果用vector<vector<int>*>表示一定数量的一级指针也是可以的,只是访问方式就需要解引用了

(2)第二步,初始化

我们可以先通过下标访问里面的vector<int>,再调用resize给对应的vector<int>开辟空间+初始化

(3)计算对应的位置

可以看到左边是从下标2开始,右边是从下标1开始,那么空格的元素为【i-1,j-1】+【i-1,j】之和

 代码展示
class Solution { public: vector<vector<int>> generate(int numRows) { //开辟行数 vector<vector<int>> V(numRows); //开辟二维数组(开辟+初始化) for(int i=0;i<numRows;i++) { V[i].resize(i+1,1); } //计算指定元素 for(int i=2;i<numRows;i++) { for(int j=1;j<i;j++) { V[i][j]=V[i-1][j]+V[i-1][j-1]; } } return V; } };

电话号码字母组合

https://leetcode.cn/problems/letter-combinations-of-a-phone-number

题目解读:

我们可以看到每个数字都代表着一串字符,题目会给你一串字符数字,让你用这些数字所映射的字符串去根据里面的字符组合出不同的字符串,例如:给你“34”。3代表“def”,4代表“ghi”,它们可以组合出:“dg”、“dh”、“di”、“eg”、“eh”、“ei”、“fg”、“fh”、“fi”,将这些字符串放在vector里面,返回即可

原理讲解

这题需要用到多参的递归,下面小编一步步讲解

(1)首先我们需要表达映射关系,比如“2”对应“abc”,“3对应“def”,以此类推

//映射关系 string str[10]={"","","abc","def","ghi","jkl","mno","pqs","tuv","wxyz"};

(2)递归函数参数:题目给的数字组合、数字下标、组合的字符串、vector<string>存储

class Solution { //映射关系 string str[10]={"","","abc","def","ghi","jkl","mno","pqs","tuv","wxyz"}; public: //递归函数 void Compare(string digits,int val,string news,vector<string>&) { //函数实现 } vector<string> letterCombinations(string digits) { vector<string> V; //如果是空串,直接返回 if(digits.empty()) { return V; } //调用递归函数 Compare(digits,0,"",V); //返回结果 return V; } };

参数的解释:digits方便我们找到数字字母、val为数字下标、news是组合得到的字符串

(2)首先要拿到第一位数字字母映射的内容,由数字下标找到数字映射的字符串

/拿到映射内容 int tmp=digits[val]-'0'; string stl_=str[tmp];

(3)此时我们可以通过循环控制当前的字符:def,例如:

//从第一个字母开始组合 for(int i=0;i<stl_size();i++) { //进入第二层for循环 }

此时 i 为0,也就是指向d,下面我们想组合出 dg、dh、di,还需要调用递归函数

(4)函数的参数:

Compare(digits,val+1,news+stll[i],V);

 ghi 是第二个数字映射的字符串,但是又不能真正改变val,因为后面要回溯

 此时相当于news从原来的 "" 变成了 "d",也不能真正改变news,因为后面要回溯否则就累积了

(5)现在是递归的结束条件,如果组合完每层的字母,那就返回,回到第一层for循环,重新开始

//递归结束条件 if(val==digits.size()) { //存储 V.push_back(news); return; }

梳理递归思路:

代码展示
class Solution { //映射关系 string str[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; public: //递归函数 void Compare(string digits,int val,string news,vector<string>& V) { //递归结束条件 if(val==digits.size()) { //存储 V.push_back(news); return; } //拿到映射内容 int tmp=digits[val]-'0'; string stll=str[tmp]; //从第一个字母开始组合 for(int i=0;i<stll.size();++i) { //进入第二层for循环 Compare(digits,val+1,news+stll[i],V); } } vector<string> letterCombinations(string digits) { vector<string> V; if(digits.empty()) { return V; } //调用递归函数 Compare(digits,0,"",V); //返回结果 return V; } };

整型去重

https://leetcode.cn/problems/remove-duplicates-from-sorted-array

原理讲解 

(1)首先我们不管此类去重题有没有序,如果没有,调用Sort函数先排序

(2) 如果本身已经有序,使用:unique+erase 去重组合即可(适用任何类型)

unique 接口作用:

返回一个迭代器,指向去重后序列的末尾(即最后一个不重复元素的下一个位置)

unique 接口参数:

序列范围:begin(),end()

erase 接口作用:

指定删除范围内的元素,并将之后的元素前移

注意:unique 的范围必须有序,且必须保存返回值作为erase的输入范围点

           erase之后迭代器会失效,如果需要重复使用,需要接收erase的返回值

例如:

 代码展示
class Solution { public: int removeDuplicates(vector<int>& nums) { auto new_end=unique(nums.begin(),nums.end()); nums.erase(new_end,nums.end()); return nums.size(); } };

找只出现一次的数字II

https://leetcode.cn/problems/single-number-iii

原理讲解

(1)先算出不同的两个整型的异或结果(比如:1、2、1、3、2、5,异或和结果为6) 

(2)找到找到最低位的1(注意整型溢出)

          int mask = (tmp == INT_MIN ? tmp : tmp & (-tmp));

(3)将最低位为1的进行分组,最后得到只出现一次的两个数字

代码展示
class Solution { public: vector<int> singleNumber(vector<int>& nums) { //计算异或和 int tmp = 0; for (auto e : nums) { tmp ^= e; } //算最低位的1 int mask = (tmp == INT_MIN ? tmp : tmp & (-tmp)); //分组异或 int a = 0; int b = 0; for (auto e : nums) { if (e & mask) { a ^= e; } else { b ^= e; } } return {a, b}; } };

只出现一次的数字III

https://leetcode.cn/problems/single-number-iii

原理讲解

 出现3次的数字它的该为加起来至少是3,例如:

代码展示
class Solution { public: int singleNumber(vector<int>& nums) { int ans = 0; //遍历二进制的每一位 for (int i = 0; i < 32; ++i) { int total = 0; for (auto num: nums) { //统计该位1的个数 total += ((num >> i) & 1); } //模3去重 if (total % 3) { ans |= (1 << i); } } return ans; } };
 

                                                  【雾非雾】期待与你的下次相遇! 

Read more

Boss直聘自动化求职脚本完整教程:3步实现批量简历投递

还在为每天重复点击投递按钮而疲惫不堪吗?Boss直聘批量投简历工具正是你需要的求职助手!这款基于浏览器扩展的自动化脚本能够智能筛选岗位并快速完成简历投递,让求职过程变得高效而轻松。 【免费下载链接】boss_batch_pushBoss直聘批量投简历,解放双手 项目地址: https://gitcode.com/gh_mirrors/bo/boss_batch_push 🔍 求职效率痛点分析与解决方案 为什么需要批量投递工具? 传统求职方式存在诸多痛点:手动筛选耗时耗力、优质岗位容易遗漏、投递速度受限平台规则。Boss直聘批量投简历工具通过自动化技术完美解决这些问题,实现精准投递与效率提升的完美结合。 Boss直聘批量投简历工具的配置面板,展示公司名过滤、岗位关键词、薪资范围等核心筛选选项 🛠️ 环境准备与脚本部署 浏览器插件安装步骤详解 首先确保你的浏览器已安装浏览器扩展插件,这是运行自动化脚本的基础环境。支持Chrome、Edge、Firefox等所有主流浏览器版本。 脚本获取与安装完整流程 访问项目仓库获取最新版本脚本代码,在浏览器扩展插件中新建脚本并

By Ne0inhk
【Linux大神器】搭建网站必学的Linux的二十多条命令,老司机带你快速上手部署项目到网页,面试常考,万字解析,建议收藏 ! ! !

【Linux大神器】搭建网站必学的Linux的二十多条命令,老司机带你快速上手部署项目到网页,面试常考,万字解析,建议收藏 ! ! !

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. 🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!! 引言 在当今数字化时代,搭建网站已成为一项重要技能。而要熟练搭建网站,Linux 指令是必不可少的工具。它们就像是打开网站建设大门的钥匙,能让你在数字世界中自由驰骋。让我们一起探索这些必学的 Linux 指令,开启精彩的网站搭建之旅吧! 目录 1. Linux 的初识以及使用云服务器 2. Linux的常用指令 3. 部署项目 一. Linux 的初识以及使用云服务器 1. Linux 的初识 Linux 是和 window 并列的一种操作系统。 Linux是一种 自由和开发源 代码的 类 Unix 操作系统 ,具体稳定性强,安全性高,多任务处理能力出色的特点。 Linux创始人: Linus Torvalds(

By Ne0inhk
【OpenClaw从入门到精通】第05篇:实战!OpenClaw自动化搞定邮件/日历/文件管理(2026实测避坑版)

【OpenClaw从入门到精通】第05篇:实战!OpenClaw自动化搞定邮件/日历/文件管理(2026实测避坑版)

摘要:本文聚焦OpenClaw核心实用场景,手把手教你实现邮件、日历、文件管理的全自动化。通过安装三大核心技能,配置IMAP/SMTP邮箱、跨平台日历及文件沙盒权限,结合4个虚拟实战案例,演示从邮件自动摘要、会议冲突预警到下载文件夹分类的完整流程。文中包含2026实测的命令代码、配置步骤、排障方案,所有案例需在测试环境验证,代码未上传GitHub。兼顾新手入门与进阶需求,让OpenClaw从“能聊天”升级为“能干活”,帮你节省80%重复工作时间。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:高并发+性能调优终极实战】【Coze搞钱实战:

By Ne0inhk
【Linux】Linux下的静态链接的底层逻辑

【Linux】Linux下的静态链接的底层逻辑

前言:欢迎各位光临本博客,这里小编带你直接手撕**,文章并不复杂,愿诸君**耐其心性,忘却杂尘,道有所长!!!! IF’Maxue:个人主页  🔥 个人专栏: 《C语言》 《C++深度学习》 《Linux》 《数据结构》 《数学建模》 ⛺️生活是默默的坚持,毅力是永久的享受。不破不立! 文章目录 * 静态链接与动态链接原理详解 * 1. **目标文件:代码的“零件包”** * 2. **链接过程:合并零件包,解决“地址谜题”** * 3. **地址重定位:磁盘上的“虚拟地图”** * 4. **动态链接:共享库的魔法** * 总结 这是一篇博客的雏形,请用通俗化的语言结合图片内容和上下文,不要修改减少或增添所有的图片,以图片为中心上下文内容要强关联,对其进行优化, 要求:通俗化,简洁化,分段式,详细化,

By Ne0inhk