1. 项目概述
作为一名长期奋战在算法竞赛一线的开发者,我深知vector在实际编程中的重要性。今天我想和大家深入探讨两个经典的vector算法题目:118. 杨辉三角和26. 删除有序数组中的重复项。这两个题目看似简单,却蕴含着vector操作的精华,也是面试中的高频考点。
杨辉三角是数学中的经典概念,在编程中如何用vector高效生成是一个值得研究的问题。而删除有序数组中的重复项则考察了我们对vector底层实现的理解,特别是快慢指针技巧的应用。这两个题目分别代表了vector的两种典型使用场景:动态构建二维结构和原地修改一维数组。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 杨辉三角的vector实现解析
2.1 杨辉三角的数学特性
杨辉三角,又称帕斯卡三角,是一个无限对称的数字金字塔。它的每一行都对应着二项式系数,具有以下重要特性:
- 每行首尾数字都是1
- 每个内部数字等于它正上方数字和左上方数字之和
- 第n行有n个元素
在C++中,我们可以用vector<vector
2.2 动态构建的实现思路
实现杨辉三角的关键在于如何高效地构建这个二维结构。以下是具体实现步骤:
cpp复制vector<vector<int>> generate(int numRows) {
vector<vector<int>> triangle;
for(int i=0; i<numRows; ++i){
vector<int> row(i+1, 1); // 初始化当前行,所有元素设为1
for(int j=1; j<i; ++j){ // 跳过首尾元素
row[j] = triangle[i-1][j-1] + triangle[i-1][j];
}
triangle.push_back(row);
}
return triangle;
}
这个实现的时间复杂度是O(n²),空间复杂度也是O(n²),其中n是行数。我们利用了vector的push_back方法来动态添加每一行。
2.3 优化与注意事项
在实际编码中,有几个关键点需要注意:
- 边界条件处理:当numRows为0时的特殊情况
- 内存预分配:可以使用reserve预先分配空间提高性能
- 行索引处理:注意i和j的取值范围,避免越界访问
提示:在面试中,面试官可能会要求你解释为什么内部循环从j=1开始,到j<i结束。这是为了跳过每行的首尾元素,因为它们总是1。
3. 删除有序数组中的重复项
3.1 问题分析与快慢指针法
这个问题要求我们在不使用额外数组的情况下,原地删除有序数组中的重复元素,并返回新长度。关键在于理解"原地"操作的含义,这正是vector的优势所在。
快慢指针法是解决这类问题的经典方法:
- 慢指针(slow)指向当前唯一元素的末尾
- 快指针(fast)遍历整个数组
- 当发现新元素时,将其复制到slow+1位置,然后slow前进
3.2 具体实现与代码解析
cpp复制int removeDuplicates(vector<int>& nums) {
if(nums.empty()) return 0;
int slow = 0;
for(int fast=1; fast<nums.size(); ++fast){
if(nums[fast] != nums[slow]){
nums[++slow] = nums[fast];
}
}
return slow+1;
}
这个算法的时间复杂度是O(n),空间复杂度是O(1),非常高效。它充分利用了vector支持随机访问的特性。
3.3 常见错误与调试技巧
在实际实现中,开发者常犯的错误包括:
- 忘记处理空数组的情况
- 慢指针的初始值设置错误
- 返回长度计算错误(应该是slow+1而非slow)
调试时可以打印出每步操作后的数组状态,帮助理解指针移动的逻辑:
code复制初始状态:[0,0,1,1,1,2,2,3,3,4]
fast=1: [0,0,1,1,1,2,2,3,3,4] (重复,不移动slow)
fast=2: [0,1,1,1,1,2,2,3,3,4] (移动slow到1,复制nums[2])
fast=5: [0,1,2,1,1,2,2,3,3,4] (移动slow到2,复制nums[5])
...
4. vector的底层原理与性能考量
4.1 vector的内存管理机制
理解vector的底层实现对于优化算法性能至关重要。vector是一个动态数组,它:
- 在堆上分配连续内存空间
- 当容量不足时,会重新分配更大的内存(通常是当前大小的2倍)
- 将元素从旧内存复制到新内存
- 释放旧内存
这种机制解释了为什么在预先知道大小的情况下,使用reserve可以显著提高性能。
4.2 两种算法的性能对比
杨辉三角算法:
- 涉及频繁的vector扩容操作
- 每次push_back都可能导致内存重新分配
- 解决方案:预先计算所需空间或用reserve优化
删除重复项算法:
- 完全原地操作,不涉及内存分配
- 仅依赖元素比较和赋值
- 性能非常稳定
4.3 实际应用中的选择建议
根据不同的应用场景选择合适的方法:
- 需要频繁随机访问:优先考虑vector
- 需要频繁在中间插入删除:考虑list
- 元素唯一性重要:考虑set或unordered_set
- 需要同时维护键值对:考虑map
5. 扩展思考与练习题
为了加深对vector算法的理解,我推荐以下扩展练习:
- 修改杨辉三角代码,使其只返回指定的第n行
- 实现删除排序数组中的重复项II(允许最多重复两次)
- 尝试用单vector而非vector<vector
>实现杨辉三角 - 比较vector和原生数组在算法实现上的性能差异
这些练习将帮助你更深入地掌握vector在各种算法场景中的应用技巧。在实际编程中,理解数据结构的底层原理往往能帮助我们写出更高效的代码。
