最近思考到这样一个题目:在STL的set和vector容器里存储了1亿个QQ号,编写函数删除奇数QQ号。

1. STL容器简介

首先了解一下 set 和 vector 以及其他类似的 STL 容器:

实现描述:

容器 描述
vector 向量,一个有着N个或更多连续存储的元素的数组
list 列表,一个由节点组成的双向链表,每个节点中包含一个元素。
deque 双队列,一个有着N个或更多连续存储的指向不同元素的指针组成的数组
set 集合,一个由节点组成的红/黑树,每个节点包含一个元素,节点之间以某种作用与元素对的谓词排序,没有两个不同的元素能够拥有相同的次序。
multiset 多重集合,允许存在两个次序相同的元素的集合。
map 映射,一个由{键 , 值}对组成的集合,以某种作用于键对上的谓词排序,使用pair<键, 值>
multimap 多重映射,允许键有重复的,即一个键可以有多个对应的值。

时间和空间复杂度:

容器 vector deque list set/map
插入/删除 N N 常量 log(N)
从前面添加 N 常量 常量 log(N)
find(val) N N N log(N)
X(N) 常量 常量 N N
指针 0 1 2 3

其他容器适配器

这些容器几乎是由其他容器实现的容器,只是对存取元素方面进行了部分的限制。

容器 描述
stack 栈,后进先出的队列。
queue 队列,先进先出。
priority_queue 优先队列,一个队列,其中元素的次序是由作用于所存储值对上的某种谓词决定的,拥有高优先级的元素会先被出队。

2. 算法解析

第一个思路就是使用erase函数一个个去删,(不知道有没有什么更好的方法请在评论里指点一下,谢谢)这里,set和vector的存储方式是不一样的。但是它们都提供了一个删除元素的接口erase

// set
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
size_type erase( const Key& key);
  • 第一个成员函数:删除 set 中由迭代器 it 指向的元素;
  • 第二个成员函数:删除 set 中区间为 [first , last )中的所有元素;
  • 第一和第二个成员函数都返回一个迭代器,指向紧接着被删除元素的下一个元素,如果没有这样的元素,则迭代器指向 end()。
  • 第三个成员函数:删除 set 中区间为 [lower_bound(key) , upper_bound(key) )中的具有给定排序键key的所有元素,返回删除元素的个数
// vector , list ,  deque
iterator erase(iterator it);
iterator erase(iterator first, iterator last);
  • 第一个成员函数:删除 vector/list/deque 中由迭代器 it 指向的元素;
  • 第二个成员函数:删除 vector/list/deque 中区间为 [first , last )中的所有元素;
  • 第一和第二个成员函数都返回一个迭代器,指向紧接着被删除元素的下一个元素,如果没有这样的元素,则迭代器指向 end()。
  • vector时,删除 N 个元素将导致调用 N 次析构函数以及从删除点至序列末端的每个元素都被赋值一次。由于不需要进行存储空间的重新分配,所以只有从指向第一个被删除元素到序列末端这个区域的迭代器以及引用才会失效。
  • list时,删除N个元素将调用N次析构函数。由于没有进行任何重新分配发生,只有指向被删除对象的迭代器和引用才会变为无效。
  • deque时,删除N个元素将导致N次调用析构函数以及从删除点至序列较近的末端的每个元素都被赋值一次。在序列的两端删除一个元素仅使得原先指向被删除元素的迭代器和引用变得无效,否则,删除一个元素将导致所有的迭代器和引用都变的无效。

了解了这个以后,能发现,算法题中的说存储在set和vector中,其实其内部存储是不一样的,删除的实现原理也是不同的。但都可以用同一个接口erase()去实现!及时这时候添加说还存储在list和deque中,也是可以使用的。我们可以写两个函数去实现这个功能,但由于在两个容器中,而调用的接口又都是一样的,所以自然而然想到可以使用模板函数!这是其一。

第二,题目中说是QQ号,众所周知,QQ目前已经多达11位了,以后还会更长,所以将QQ号设为整型肯定是不合适的了,所以这里需要使用long long 。同时,遍历容器时,肯定是要使用迭代器来进行遍历的,这样能保证速度。

第三,题目中说一亿个QQ号,目前还不知道这里藏着什么坑,感觉是有的,我写的代码反正是死掉了,一亿条,添加和删除的循环都搞死了。还请大神帮忙分析分析!

所以基于以上分析,写出以下代码:

#include <utility>
#include <set>
#include <vector> typedef long long dlong; template <typename T>
void qq_delete_stl_template(T &t){
typename T::iterator it=t.begin(); //typename用来说明T::iterator是一个类型,
//否则iterator会被认为是T中的一个成员变量
while(it!=t.end()){ //每次删除后都会导致t.end()指向的都是不同的位置
if((*it)&1){ //奇数
it=t.erase(it); //删除迭代起指向的内容,并返回删除后的下一项内容
}else{
++it;
}
}
} //调用时应该是:
set<dlong> s; //假设s里存有1亿个QQ号
qq_delete_stl_template(s);
vector<dlong> v; //假设v里存有1亿个QQ号
qq_delete_stl_template(v);

分析的比较浅显,希望大神指教!

完整测试源码

附录

STL容器及算法题:删除奇数的QQ号的更多相关文章

  1. 【坐在马桶上看算法】算法4:队列——解密QQ号

            新学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问QQ号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则. ...

  2. 算法5:队列——解密 QQ 号

    新学期开始了,小哈是小哼的新同桌(小哈是个小美女哦~),小哼向小哈询问 QQ 号,小哈当然不会直接告诉小哼啦,原因嘛你懂的.所以小哈给了小哼一串加密过的数字,同时小哈也告诉了小哼解密规则.规则是这样的 ...

  3. 刷题常用的STL容器总结

    本文归纳总结刷题常用到STL容器以及一些标准算法,主要包括: string.vector.map.pair.unordered_map.set.queue.priority_queue.stack,以 ...

  4. 每天一道算法题(4)——O(1)时间内删除链表节点

    1.思路 假设链表......---A--B--C--D....,要删除B.一般的做法是遍历链表并记录前驱节点,修改指针,时间为O(n).删除节点的实质为更改后驱指针指向.这里,复制C的内容至B(此时 ...

  5. C++进阶 STL(1) 第一天 [容器,算法,迭代器] string容器 vector容器 deque容器

    课程大纲 02实现基本原理 容器,算法,迭代器 教室:容器 人:元素 教室对于楼:容器 序列式容器: 容器元素在容器中的位置是由进入容器的时间和地点来决定 序列式容器 关联式容器: 教室中 按年龄排座 ...

  6. 【pat】C++之刷题常用STL容器整理

    1.vector 动态数组,方便的动态扩容,方便的变量初始化(int类型默认初始化为0,bool默认初始化为false),可以用来实现邻接表(结点数太多的图). 头文件 #include<vec ...

  7. 《STL源码剖析》——第五、六:关联容器与算法

    第五章.关联容器  5.0.关联容器 标准的STL关联式容器分为set(集合)和map(映射表)两大类,以及这两大类的衍生体multiset(多键集合)和multimap(多键映射表).这些容器的底层 ...

  8. STL容器删除元素的陷阱

    今天看Scott Meyers大师的stl的用法,看到了我前段时间犯的一个错误,发现我写的代码和他提到错误代码几乎一模一样,有关stl容器删除元素的问题,错误的代码如下:std::vector< ...

  9. STL容器的遍历删除

    STL容器的遍历删除 今天在对截包程序的HashTable中加入计时机制时,碰到这个问题.对hash_map中的每个项加入时间后,用查询函数遍历hash_map,以删除掉那些在表存留时间比某个阈值长的 ...

随机推荐

  1. PIE SDK正射校正

    1. 算法功能简介 正射校正是对影像空间和几何畸变进行校正生成多中心投影平面正射图像的处理过程.它除了能纠正一般系统因素产生的几何畸变外,还可以消除地形引起的几何畸变 PIE支持算法功能的执行,下面对 ...

  2. cas aqs lock之间的关系

    CAS 对应cpu的硬件指令, 是最原始的原子操作 cas主要是在AtomicInteger AtomicXXX类中使用, 用于实现线程安全的自增操作 ++. 对应一个unsafe对象, 根据os平台 ...

  3. Vue 项目启动抛出 Error/ No PostCSS Config found in

    项目启动时抛出 Error: No PostCSS Config found in … 的错误表示某个 css 文件不能被引入 解决办法: module.exports = { plugins: { ...

  4. Linux下jenkins改端口、解决内存溢出、版本升级

    1.新版本的jenkins修改端口新版本jenkins的配置文件在/etc/sysconfig/jenkinsvi /etc/sysconfig/jenkins找到JENKINS_PORT=" ...

  5. pipline --学习 (-)

    一,语法: 编写位置: pipline 启动docker pipeline { agent { docker 'maven:3.3.3' } stages { stage('build') { ste ...

  6. (Frontend Newbie)Web三要素(三)

    上一篇简单介绍了Web三要素中的层叠样式表,本篇主要介绍三要素中最后一个,也是最难掌握的一个-----JavaScript. JavaScript 老规矩不能破,先简要交代 JavaScript 的历 ...

  7. Beam概念学习系列之SDKs

    不多说,直接上干货! https://beam.apache.org/get-started/beam-overview/ Beam SDK 提供了一个统一的编程模型,来处理任意规模的数据集,其中包括 ...

  8. Python 递归返回树形菜单JSON串 <flask>

    需求:菜单管理功能(增.删.改),多级树形菜单展示 数据库表设计 create table if not exists Menu( id serial primary key , title ) no ...

  9. 记自己的hexo个人博客

    https://othercoding.github.io/

  10. 深入理解JavaScript系列(5):强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大.实 ...