国庆放假第二天,奥利给,继续干。
看一下vector的构造函数:
(1)默认构造函数:
vector s1();
(2)复制初始化构造:
vector s2(10, 3);
(3)范围区间构造:
甚至可以用string的begin,end:
string v1("hello");
vector s3(v1.begin(), v1.end());
利用下标实现遍历:
string v1("hello");
for (size_t i = 0; i < v1.size(); i++)
{
cout << v1[i] << " ";
}
cout << endl;
string v1("hello");
vector s3(v1.begin(), v1.end());
vector::iterator it = s3.begin();
while (it != s3.end()) {
cout << *it << " ";
it++;
}
cout << endl;
因为是
如果把vector的模版类型改为char的话输出的就是“hello”:
string v1("hello");
vector s3(v1.begin(), v1.end());
for (auto h1 : s3)
{
cout << h1 << " ";
}
cout << endl;
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
解析:
扩容要用的函数参考:
如下代码:
vector s1;
auto sz = s1.capacity();
for (size_t i = 0; i < 100; i++)
{
s1.push_back(i);
if (sz != s1.capacity())
{
sz = s1.capacity();
cout << "扩容:" << s1.capacity() << endl;
}
}
if (sz != s1.capacity())
{
sz = s1.capacity();
}这个if语句的作用是什么呢?
如果删掉if语句运行:
它会没执行一次循环就扩容一次,最后扩容一百次,if语句的作用就是限制了扩容,让它只有在空间不够的条件下菜扩容。
观察扩容的数字规律:发现它是一次扩容1.5的(受内存对齐影响看起来不完全是1.5倍扩容)。
我们发现它是二倍扩容的关系。
同样一段代码,用reserve和resize的运行结果区别:
vector s1;
auto sz = s1.capacity();
//s1.reserve(100);
//s1.resize(100);
cout << "开空间:" << s1.capacity() << endl;
for (size_t i = 0; i < 100; i++)
{
s1[i]=i;
if (sz != s1.capacity())
{
sz = s1.capacity();
cout << "扩容:" << s1.capacity() << endl;
}
reserve:
因为reserve只是提前开空间,开的空间够用了就不再扩容了,它不会往里面写值。
但是resize是size和capacity都扩到了100,并且会实际往里面写入值,写100个int需要400个字节,所以还需要接着扩容。
用reserve开辟100个空间,然后遍历一下,打印出来:
vector s1;
auto sz = s1.capacity();
s1.reserve(100);
//s1.resize(100);
cout << "开空间:" << s1.capacity() << endl;
for (size_t i = 0; i
这是因为reserve只把capacity开辟了100个空间,但是size还是0:
那么强行写入呢?既然空间已经开出来了,那直接往里面写入会怎么样:
vector s1;
auto sz = s1.capacity();
s1.reserve(100);
//s1.resize(100);
cout << "开空间:" << s1.capacity() << endl;
for (size_t i = 0; i <100; i++)
{
s1[i]=i;
}
for (auto ch : s1)
{
cout << ch << endl;
}
会报异常:
如果就是想访问呢,解决办法:
(1)用resize,把size也开成100,这样就不会越界了:
vector s1;
auto sz = s1.capacity();
//s1.reserve(100);
s1.resize(100);
cout << "开空间:" << s1.capacity() << endl;
for (size_t i = 0; i <100; i++)
{
s1[i]=i;
}
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
(2)不用下标访问就不会越界,用push_back:
vector s1;
auto sz = s1.capacity();
s1.reserve(100);
//s1.resize(100);
cout << "开空间:" << s1.capacity() << endl;
for (size_t i = 0; i <100; i++)
{
s1.push_back(i);
}
for (auto ch : s1)
{
cout << ch << " ";
}
vector不支持流插入,流提取,也就是我们直接把值打印出来:
这是因为vector是一个顺序表,如果直接把值打印出来编译器不明白是什么意思,假如你插入1,2,3,4
直接打印出来就是:
1234
那编译器会认为这是整数1234还是12 ,34还是123,4还是1,2,34……
那么为什么string可以直接输出呢?
string有直接流提取流输出的需求,列如输入"hello world",直接输出"hello world",就是我们想要的效果了,编译器不存在看不懂的情况。
解决方法,先遍历一遍,把我们需要分别的地方分别好再输出(列如数字之间的空格):
vector s1;
s1.push_back(1);
s1.push_back(2);
s1.push_back(3);
s1.push_back(4);
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
pos我们可以用迭代器里的begin就可以找到头部了:
vector s1;
s1.push_back(1);
s1.push_back(2);
s1.push_back(3);
s1.push_back(4);
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
s1.insert(s1.begin(), 0);
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
vector没有写find,但是在算法里面有find,这个find在标准库里,是一个模版,大家都可以用,如下:
我们可以通过find找到值为3的数字,再通过inser()在3前插入一个30:
auto it=find(s1.begin(),s1.end(),3);
if (it != s1.end())
{
s1.insert(it, 30);
}
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
删除一个指定的数:
先通过find找到这个数,然后再通过eraser删除这个数:
auto it1 = find(s1.begin(), s1.end(), 30);
if (it1 != s1.end())
{
s1.erase(it1);
}
for (auto ch : s1)
{
cout << ch << " ";
}
cout << endl;
可以用clean来释放size,但是clean只能释放size不能释放空间(capacity):
s1.clean();
要想手动释放空间不能通过调用析构函数来释放,因为析构函数不能被显示调用。
也就是先把size释放为0,然后再用hrink_to_fit会把capacity缩到和size一样大小:
s1.shrink_to_fit();
136. 只出现一次的数字 - 力扣(LeetCode)
思路:
也就是异或是符合结合律的,让这个数组内部自己慢慢异或,最后的结果一定就是那个数组中唯一的值,因为其他出现两次或三次的数都被异或为0了。
代码:
写一个循环,把这个数组遍历一下,然后让数组内部异或,把最后得出的值返回即可:
class Solution {
public:
int singleNumber(vector& nums) {
size_t val=0;
for(size_t i=0;i
但是这个代码是通过不了的,因为vector是一个顺序表,遍历它需要先存值,而存值需要开空间,所以我们需要reverse或者resize一个空间。
reverse只开辟capacity不开辟size大小无法遍历,所以我们用reszie。
案列能通过多少取决于你开多少空间和size:
:
因为我们并不知道需要开多大空间,只能自己慢慢试,最后还开多了。因此我们可以用范围for,范围for会自动开辟空间,自己设置条件,自己++:
class Solution {
public:
int singleNumber(vector& nums) {
size_t val=0;
//手动开空间,手动遍历:
// nums.resize(100000);
// for(size_t i=0;i
课习题(3)118. 杨辉三角 - 力扣(LeetCode)
思路:首先要知道 vector
vector
那么 vector
那么我们应该怎么去做一个杨辉三角的树呢
其实就是二维数组。
思路:
我们可以把一个顺序表看做一行,我们访问哪个vector就是访问那一行,
然后我们就可以把变成0的那个位置进行操作:
让这个位置的值=上一行同一个下标列左边的值+上一行下标列-1的值。
这个部分要结合vector的与源码来看的。
第一个版本:112git1 · 孙鹏宇/孙鹏宇的第一个仓库 - 码云 - 开源中国 (gitee.com)