int GetUglyNumber_Solution(int index) {
if (index <= 0) return 0;//返回错误信息
vector<int> uglyNums;
uglyNums.push_back(1);
//定义三个迭代器Tx,分别表示第一个乘以x后大于当前最大丑数的元素的位置
vector<int>::iterator T2 = uglyNums.begin();
vector<int>::iterator T3 = T2;
vector<int>::iterator T5 = T2;
while (uglyNums.size() < index) {
while (*T2 * 2 <= uglyNums.back()) { ++T2; }
while (*T3 * 3 <= uglyNums.back()) { ++T3; }
while (*T5 * 5 <= uglyNums.back()) { ++T5; }
int min = *T2 * 2;
int U3 = *T3 * 3;
int U5 = *T5 * 5;
if (U3 < min) min = U3;
if (U5 < min) min = U5;
uglyNums.push_back(min);//这里会使得迭代器失效
}
return uglyNums.back();
}
然后调试的时候发现不对啊,第二次循环的时候,三个迭代器都失效了。然后想起,vector的内存分配机制
1.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。
2.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时begin和end操作返回的迭代器都会失效。
3.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。
对于vector而言,添加和删除操作可能使容器的部分或者全部迭代器失效。vector元素在内存中是顺序存储,如果当前容器中已经存在了10个元素,现在又要添加一个元素到容器中,但是内存中紧跟在这10个元素后面没有一个空闲空间,而vector的元素必须顺序存储一边索引访问,所以我们不能在内存中随便找个地方存储这个元素。于是vector必须重新分配存储空间,用来存放原来的元素以及新添加的元素:存放在旧存储空间的元素被复制到新的存储空间里,接着插入新的元素,最后撤销旧的存储空间。这种情况发生,一定会导致vector容器的所有迭代器都失效。我们看到实现上述所说的分配和撤销内存空间的方式以实现vector的自增长性,效率是极其低下的。为了使vector容器实现快速的内存分配,实际分配的容器会比当前所需的空间多一些,vector容器预留了这些额外的存储区,用来存放新添加的元素,而不需要每次都重新分配新的存储空间。你可以从vector里实现capacity和reserve成员可以看出这种机制。capacity和size的区别:size是容器当前拥有的元素个数,而capacity则指容器在必须分配新存储空间之前可以存储的元素总数。
int GetUglyNumber_Solution(int index) {
if (index <= 0) return 0;//返回错误信息
vector<int> uglyNums;
uglyNums.push_back(1);
int T2, T3, T5;
T2 = T3 = T5 = 0;
while (uglyNums.size() < index) {
while (uglyNums[T2] * 2 <= uglyNums.back()) { ++T2; }
while (uglyNums[T3] * 3 <= uglyNums.back()) { ++T3; }
while (uglyNums[T5] * 5 <= uglyNums.back()) { ++T5; }
int min = uglyNums[T2] * 2;
int U3 = uglyNums[T3] * 3;
int U5 = uglyNums[T5] * 5;
if (U3 < min) min = U3;
if (U5 < min) min = U5;
uglyNums.push_back(min);
}
return uglyNums.back();
}
皮这一下我很开心