#include
//vector是动态数组,在尾部增删的复杂度是O(1)
vector vec; //声明一个int型向量
vector vec(5); //声明一个初始大小为5的int向量
vector vec(10, 1); //声明一个初始大小为10且值都是1的向量
vector vec(tmp); //声明并用tmp向量初始化vec向量
vector tmp(vec.begin(), vec.begin() + 3); //用向量vec的第0个到第2个值初始化tmp
int arr[5] = {1, 2, 3, 4, 5};
vector vec(arr, arr + 5); //将arr数组的元素用于初始化vec向量
//说明:当然不包括arr[4]元素,末尾指针都是指结束元素的下一个元素,
//这个主要是为了和vec.end()指针统一。
vector vec(&arr[1], &arr[4]); //将arr[1]~arr[4]范围内的元素作为vec的初始值
向量大小: vec.size();
向量最大容量: vec.max_size();
更改向量大小: vec.resize();
向量真实大小: vec.capacity();
向量判空: vec.empty();
减少向量大小到满足元素所占存储空间的大小: vec.shrink_to_fit(); //shrink_to_fit
多个元素赋值: vec.assign(); //类似于初始化时用数组进行赋值
末尾添加元素: vec.push_back();
末尾删除元素: vec.pop_back();
任意位置插入元素: vec.insert();//例如vec.insert(vec.begin(),1);
任意位置删除元素: vec.erase();
交换两个向量的元素: vec.swap();
清空向量元素: vec.clear();
开始指针:vec.begin();
末尾指针:vec.end(); //指向最后一个元素的下一个位置
指向常量的开始指针: vec.cbegin(); //意思就是不能通过这个指针来修改所指的内容,但还是可以通过其他方式修改的,而且指针也是可以移动的。
指向常量的末尾指针: vec.cend();
下标访问: vec[1]; //并不会检查是否越界
at方法访问: vec.at(1); //以上两者的区别就是at会检查是否越界,是则抛出out of range异常
访问第一个元素: vec.front();
访问最后一个元素: vec.back();
返回一个指针: int* p = vec.data(); //可行的原因在于vector在内存中就是一个连续存储的数组,所以可以返回一个指针指向这个数组。这是是C++11的特性.
很方便地求和:accumulate(vec.begin(),vec.end(),0);
#include
//List定义和初始化:
listlst1; //创建空list
list lst2(5); //创建含有5个元素的list
listlst3(3,2); //创建含有3个元素的list
listlst4(lst2); //使用lst2初始化lst4
listlst5(lst2.begin(),lst2.end()); //同lst4
//List常用操作函数:
Lst1.back() //返回最后一个元素
Lst1.begin() //返回指向第一个元素的迭代器
Lst1.front() //返回第一个元素
Lst1.end() //返回末尾的迭代器
Lst1.clear() //删除所有元素
Lst1.empty() //如果list是空的则返回true
Lst1.erase() //删除一个元素
Lst1.pop_back() //删除最后一个元素
Lst1.pop_front() //删除第一个元素
Lst1.push_back() //在list的末尾添加一个元素
Lst1.push_front() //在list的头部添加一个元素
Lst1.max_size() //返回list能容纳的最大元素数量
Lst1.resize() //改变list的大小
Lst1.reverse() //把list的元素倒转
Lst1.size() //返回list中的元素个数
Lst1.sort() //给list排序
Lst1.unique() //删除list中重复的元素
deque dq;
dq.push_back(1); //队尾加元素
dq.push_front(1); //队首加元素
dq.pop_back(); //队尾出队
dq.pop_front(); //队首出队
实际使用时,遵循的原则:
1. 如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2. 如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3. 如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。
#include
stack s;
s.push(item); //将item压入栈顶
s.pop(); //删除栈顶的元素,但不会返回
s.top(); //返回栈顶的元素,但不会删除
s.size(); //返回栈中元素的个数
s.empty(); //检查栈是否为空,如果为空返回true,否则返回false
queue q;
q.push();
q.pop();
q.front() //访问queue队首元素
q.back() //访问queue队尾元素
q.empty() //判断queue队列空,当队列空时,返回true。
q.size() //访问队列中的元素个数
priority_queue
//Type 是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector),Functional 是比较的方式。
//创建大顶堆、小顶堆
priority_queue, less> q; //大顶堆
priority_queue, greater> q; //小顶堆
//若存入元素是pair,先比较pair的first元素,first元素相等时,再比较second元素
priority_queue,vector >,less > > q;
//自定义类型有两种方式:运算符重载 和 重写仿函数
struct cmp//重写仿函数
{
bool operator() (int a ,int b)
{
return a, cmp> q; //大顶堆
232. 用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
oolean empty() 如果队列为空,返回 true ;否则,返回 false
解题思路:
栈模拟队列的行为,需要两个栈一个输入栈,一个输出栈。在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
class MyQueue {
public:
stack instk; //输入栈
stack outstk; //输出栈
MyQueue() {
}
void push(int x) {
instk.push(x);
}
int pop() {
if(outstk.empty()){
while(!instk.empty()){
outstk.push(instk.top());
instk.pop();
}
}
int out=outstk.top();
outstk.pop();
return out;
}
int peek() {
if(outstk.empty()){
while(!instk.empty()){
outstk.push(instk.top());
instk.pop();
}
}
return outstk.top();
}
bool empty() {
return outstk.empty() && instk.empty();
}
};
225. 用队列实现栈
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。
实现 MyStack 类:
void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。
解题思路:
用两个队列q1和q2实现栈的功能,但此题和上题的输入输出栈不同,q2只是起到一个备份的作用,pop操作时把q1队尾元素以外的元素都备份到q2,然后弹出队尾元素,再把其他元素从q2存回q1。
class MyStack {
public:
queue q1;
queue q2;//q2用来备份
MyStack() {
}
void push(int x) {
q1.push(x);
}
int pop() {
int out;
while(!q1.empty()){ //把q1的元素全部放到q2(备份队列)
q2.push(q1.front());
q1.pop();
}
while(!q2.empty()){ //把备份队列中除了队尾的元素全部放回q1
out=q2.front();
q2.pop();
if(!q2.empty()){
q1.push(out);
}
}
return out;
}
int top() {
return q1.back();
}
bool empty() {
return q1.empty();
}
};
239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。
示例 1: 输入:nums = [1,3,-1,-3,5,3,6,7], k = 3 输出:[3,3,5,5,6,7]
解题思路:
此题是自己实现一个单调队列,即单调递减或单调递增的队列,因此只用访问que.front()就可以返回当前窗口的最大值。
那么单调队列的 pop 和 push 函数具体应该如何实现呢?我们可以根据以下规则进行设计:
pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
class Solution {
private:
class myqueue{
public:
deque q;
void pop(int value){
if(!q.empty() && q.front()==value){
q.pop_front();
}
}
void push(int value){
while(!q.empty() && q.back() maxSlidingWindow(vector& nums, int k) {
int n=nums.size();
myqueue que;
vector res;
for(int i=0;i
347. 前 K 个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2]
解题思路:
此题采用小顶堆进行实现,每加入一组和堆顶元素的 second 进行比较,若比它大则弹出堆顶元素并将此元素加入小顶堆,维持小顶堆的大小不变,遍历到最后里面存的就是前k个高频元素了。
class Solution {
public:
struct cmp{ //自定义比较函数
bool operator()(const pair& m, const pair& n) {
return m.second > n.second;
}
};
vector topKFrequent(vector& nums, int k) {
unordered_map occurrences;
for (auto& v : nums) {
occurrences[v]++;
}
// pair 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
priority_queue, vector>, cmp> q;
for (auto& [num, count] : occurrences) {
if (q.size() == k) {
if (q.top().second < count) {
q.pop();
q.emplace(num, count);
}
} else {
q.emplace(num, count);
}
}
vector ret;
while (!q.empty()) {
ret.emplace_back(q.top().first);
q.pop();
}
return ret;
}
};