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

article/2025/6/9 15:01:00

前引:在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;//范围forfor(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;}//算最低位的1int 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;}
};
 

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


http://www.hkcw.cn/article/eVpxYuSJEk.shtml

相关文章

【macbook】触控板手势

在 MacBook 上&#xff0c;你可以使用「触控板手势」或快捷键来实现在多个窗口/应用间切换&#xff0c;以下是几种方式&#xff1a; ✅ 1. 三指或四指左右滑动&#xff1a;切换“全屏应用”或“桌面”空间 **操作方式&#xff1a;**三指或四指在触控板上左右滑动。**适用场景&…

帝可得 - 策略管理

一. 需求说明 策略管理主要涉及到二个功能模块&#xff0c;业务流程如下&#xff1a; 新增策略: 允许管理员定义新的策略&#xff0c;包括策略的具体内容和参数&#xff08;如折扣率&#xff09; 策略分配: 将策略分配给一个或多个售货机。 graph TDA[登录系统] A --> B…

立志成为一名优秀测试开发工程师(第十一天)—Postman动态参数/变量、文件上传、断言策略、批量执行及CSV/JSON数据驱动测试

目录 一、Postman接口关联与正则表达式应用 1.正则表达式解析 2.提取鉴权码。 二、Postman内置动态参数以及自定义动态参数 1.常见内置动态参数&#xff1a; 2.自定义动态参数&#xff1a; 3.“编辑”接口练习 三、图片上传 1.文件的上传 2.上传后内容的验证 四、po…

学习路之PHP--easyswoole使用视图和模板

学习路之PHP--easyswoole使用视图和模板 一、安装依赖插件二、 实现渲染引擎三、注册渲染引擎四、测试调用写的模板五、优化六、最后补充 一、安装依赖插件 composer require easyswoole/template:1.1.* composer require topthink/think-template相关版本&#xff1a; "…

【C++高并发内存池篇】性能卷王养成记:C++ 定长内存池,让内存分配快到飞起!

&#x1f4dd;本篇摘要 在本篇将介绍C定长内存池的概念及实现问题&#xff0c;引入内存池技术&#xff0c;通过实现一个简单的定长内存池部分&#xff0c;体会奥妙所在&#xff0c;进而为之后实现整体的内存池做铺垫&#xff01; &#x1f3e0;欢迎拜访&#x1f3e0;&#xff…

前端验证下跨域问题(npm验证)

文章目录 一、背景二、效果展示三、代码展示3.1&#xff09;index.html3.2&#xff09;package.json3.3&#xff09; service.js3.4&#xff09;service2.js 四、使用说明4.1&#xff09;安装依赖4.2&#xff09;启动服务器4.3&#xff09;访问前端页面 五、跨域解决方案说明六…

nginx+Tomcat负载均衡群集

目录 一. LVS&#xff0c;HAProxy&#xff0c;Nginx的区别 1. 核心区别 2. 负载均衡算法对比 2. 1 LVS 负载均衡算法 2.2 HAProxy 负载均衡算法 2.3 Nginx 负载均衡算法 2.4 总结 二. 案例分析 1. 案例概述 (1) Tomcat 简介 (2)应用场景 2. 案例环境 3. 案例实施 …

WSL安装及使用 (适用于 Linux 的 Windows 子系统)

WSL简介 WSL&#xff1a;适用于 Linux 的 Windows 子系统&#xff0c;有1和2两个版本&#xff0c;1是windows重新实现了linux接口&#xff0c;2是原生linux内核。目前 WSL2 为默认模式&#xff0c;兼容性和性能更好。 wsl中文官网 安装 确保以下功能开启&#xff1a; 控制面…

JavaSec | SpringAOP 链学习分析

目录: 链子分析 反向分析 正向分析 poc 构造 总结 链子分析 反向分析 依赖于 Spring-AOP 和 aspectjweaver 两个包&#xff0c;在我们 springboot 中的 spring-boot-starter-aop 自带包含这俩类&#xff0c;所以也可以说是 spring boot 的原生反序化链了&#xff0c;调用…

PV操作的C++代码示例讲解

文章目录 一、PV操作基本概念&#xff08;一&#xff09;信号量&#xff08;二&#xff09;P操作&#xff08;三&#xff09;V操作 二、PV操作的意义三、C中实现PV操作的方法&#xff08;一&#xff09;使用信号量实现PV操作代码解释&#xff1a; &#xff08;二&#xff09;使…

医疗内窥镜影像工作站技术方案(续)——EFISH-SCB-RK3588国产化替代技术深化解析

一、异构计算架构的医疗场景适配 ‌多核任务调度优化‌ ‌A76/A55协同计算‌&#xff1a;4Cortex-A762.4GHz负责AI推理&#xff08;如息肉识别算法&#xff09;&#xff0c;4Cortex-A551.8GHz处理DICOM影像传输协议&#xff0c;多任务负载效率比赛扬N系列提升80%‌NPU加速矩阵…

HCIP-Datacom Core Technology V1.0_3 OSPF基础

动态路由协议简介 静态路由相比较动态路由有什么优点呢。 静态路由协议&#xff0c;当网络发生故障或者网络拓扑发生变更&#xff0c;它需要管理员手工配置去干预静态路由配置&#xff0c;但是动态路由协议&#xff0c;它能够及时自己感应网络拓扑变化&#xff0c;不路由选择…

敏捷转型:破局之道

在数字化浪潮与市场不确定性加剧的背景下&#xff0c;传统组织向敏捷组织转型已成为企业生存与发展的核心命题。这种转型并非简单的工具迭代或流程优化&#xff0c;而是涉及治理结构、文化基因与人才机制的深度重构。理解两种组织形态的本质差异&#xff0c;明确转型的适用场景…

WordPress 6.5版本带来的新功能

WordPress 6.5正式上线了&#xff01;WordPress团队再一次为我们带来了许多新的改进。在全球开发者的共同努力下&#xff0c;WordPress推出了许多新的功能&#xff0c;本文将对其进行详细总结。 Hostease的虚拟主机现已支持一键安装最新版本的WordPress。对于想要体验WordPres…

软硬解锁通用Switch大气层1.9.0系统+20.0.1固件升级 图文教程 附大气层大气层固件升级整合包下载

软硬解锁通用Switch大气层1.9.0系统20.0.1固件升级 图文教程 附大气层大气层固件升级整合包下载 大气层&#xff08;Atmosphere&#xff09;是为任天堂 Switch 主机开发的免费开源自定义固件&#xff08;CFW&#xff09;&#xff0c;由开发者 SciresM 领导的团队维护。它允许用…

Redisson学习专栏(五):源码阅读及Redisson的Netty通信层设计

文章目录 前言一、分布式锁核心实现&#xff1a;RedissonLock源码深度解析1.1 加锁机制&#xff1a;原子性与重入性实现1.2 看门狗机制&#xff1a;锁自动续期设计1.3 解锁机制&#xff1a;安全释放与通知1.4 锁竞争处理&#xff1a;等待队列与公平性1.5 容错机制&#xff1a;异…

字节新出的MCP应用DeepSearch,有点意思。

大家好&#xff0c;我是苍何。 悄悄告诉你个事&#xff0c;昨天我去杭州参加字节火山方舟举办的开发者见面会了&#xff0c;你别说&#xff0c;还真有点刘姥姥进大观园的感觉&#x1f436; 现场真实体验完这次新发布的产品和模型&#xff0c;激动的忍不住想给大家做一波分享。…

光耦电路学习,光耦输入并联电阻、并联电容,光耦输出滤波电路

一般的光耦电路&#xff0c;只需要输入限流电阻&#xff0c;输出上拉电阻即可。 实际使用时&#xff0c;比如工控等一些干扰大、存在浪涌电压等的场合&#xff0c;根据实际可以添加一些抗干扰电路、滤波电路&#xff0c;增加电路抗干扰能力。 比如&#xff1a; 1、给光耦输入两…

JVM知识

目录 运行时数据区域 程序计数器 Java虚拟机栈 局部变量表 操作数栈 动态链接 本地方法栈 Java堆 方法区 运行时常量池 字符串常量池 直接内存 Java对象的创建过程 对象的内存布局 对象的访问 常见的 GC 类型 ​​Minor GC&#xff08;Young GC&#xff09;​ …

Spring AI介绍及大模型对接

目录 1. Spring AI介绍 2. Spring AI常用组件 2.1. Chat Client API 2.2. Models 2.3. Vector Databases 2.4. RAG 2.5. MCP 3. 大模型对接举例 3.1. 获取deepseek的API keys 3.2. idea创建工程 3.3. 配置application.yml 3.4. 编写Controller测试类 3.5. 验证Con…