如何在遍历时添加要设置的元素?
How to add elements to set while traversing it?
我们有一个固定的S {1,10,100,1000,10000}
。现在我们输入一个整数x
(比如x
=4
)。
现在我们必须将 set 乘积的每个元素都添加到集合本身x
。所以终于
S={1,10,100,1000,10000,4,40,400,4000,40000}
[S
最初不限于 5 个条目]
我们只需要访问集合中的初始元素。 我尝试了以下方法:
for(auto i=s.begin();i!=s.end();i++)
{
s.insert((*i)*x);
}
这不会给出预期的结果,因为集合的大小不断增加。
我尝试的另一种方法是将所有(*i)*x
倍数存储在另一个临时集合/向量中,并在以后将其与 s 合并。 但由于原始数据集很大,它加剧了时间复杂度。 任何优化?
由于std::set
是有序的,并且迭代器不会因插入而失效,因此只要不插入到仍有待迭代的范围,就可以在迭代时简单地插入。
如果我们可以假设所有数字都是正数,那么我们可以反向迭代,因为乘法的结果总是大于输入:
for (auto it = S.rbegin(); it != S.rend(); ++it)
S.insert(*it*x);
如果x
为负数并且 set 仅包含正数,则迭代顺序无关紧要。如果集合可能包含负数,则这变得更具挑战性。
但由于原始数据集很大,它加剧了时间复杂度。
将 N 个元素插入std::set
是 O(N log N)。合并std::set
s 是 O(N log N)。合并方法不会降低渐近时间复杂度。
但是,如果您要使用std::unordered_set
,则在平均情况下合并方法将为O(N)。然而,在最坏的情况下,它仍然是 O(N log N)。我建议将合并方法与无序集一起使用。
你来了。
#include <iostream>
#include <set>
#include <iterator>
std::set<int> & update( std::set<int> &s, int value )
{
for ( auto it = rbegin( s ); it != rend( s ); ++it )
{
s.insert( *it * value );
}
return s;
}
int main()
{
std::set<int> s = { 1, 10, 100, 1000, 10000 };
for ( const auto &value : s )
{
std::cout << value << ' ';
}
std::cout << 'n';
for ( const auto &value : update( s, 4 ) )
{
std::cout << value << ' ';
}
std::cout << 'n';
return 0;
}
程序输出为
1 10 100 1000 10000
1 4 10 40 100 400 1000 4000 10000 40000
根据 C++ 20 标准(22.2.6 关联容器)
9 插入和放置构件不影响 容器的迭代器和引用,擦除成员应 仅使迭代器和对已拭除元素的引用失效。
或更通用的方法
#include <iostream>
#include <set>
#include <iterator>
std::set<int> & update( std::set<int> &s, int value )
{
auto partition = s.lower_bound( 0 );
for ( auto it = rbegin( s ); it != std::set<int>::reverse_iterator( partition ); ++it )
{
s.insert( *it * value );
}
for ( auto it = begin( s ); it != partition; ++it )
{
s.insert( *it * value );
}
return s;
}
int main()
{
std::set<int> s = { -10000, -1000, -100, -10, -1, 1, 10, 100, 1000, 10000 };
for ( const auto &value : s )
{
std::cout << value << ' ';
}
std::cout << 'n';
for ( const auto &value : update( s, 4 ) )
{
std::cout << value << ' ';
}
std::cout << 'n';
return 0;
}
程序输出为
-10000 -1000 -100 -10 -1 1 10 100 1000 10000
-40000 -10000 -4000 -1000 -400 -100 -40 -10 -4 -1 1 4 10 40 100 400 1000 4000 10000 40000
如评论中所述,使用临时集是最简单的。对于 C++17,您可以将std::set::merge
与转换为右值的临时集一起使用:
#include <algorithm>
std::set<int> s2;
std::transform(s1.cbegin(), s1.cend(), std::inserter(s2, s2.end()),
[](int orig){ return 4*orig; });
s1.merge(std::move(s2));
否则,请注意,插入集的迭代器不会失效。将此与集合是有序的事实结合起来,在您描述的场景(缩放现有值大于原始值,但小于或等于下一个现有值)的情况下,您可以在这样的循环中执行此操作:
for (auto it = s1.begin(); it != s1.end(); ++it)
it = s.insert(*it*4).first;
为了减少限制,您可以使用以下更详细的循环:
for (std::set<int>::iterator it1 = s.begin(), it2; it1 != s.end();
it1 = std::next(it1) == it2 ? std::next(it1, 2) : it2)
it2 = s.insert(*it1*4).first;
- 在QComboBox或QListWidget中设置所选元素的样式文本?
- 如果我在相应 char 数组的声明中为其提供额外的元素,是否会自动设置 NULL?
- 无法在构造函数中执行设置元素插入
- 循环中的变量被设置为下一个数组的元素始终具有相同的内存地址?
- 设置负元素特征稀疏向量C++
- 迭代时擦除设置元素///
- 为 unordered_map 中的元素设置默认构造函数(如果是 [] 运算符)
- 在C++中将指针数组的所有元素设置为 nullptr
- C++:如何将枚举元素设置为无限?
- 我们如何使用下面的集合构造函数构造设置元素
- 如何在遍历时添加要设置的元素?
- 如何通过STL设置迭代直到第二个元素
- 如何在类中初始化数组并为第一个元素设置值
- 如何将Bools中的一个元素设置为true
- 在编译时间检查模板参数类型是否设置或多键,并且容器的元素类型是算术的
- 如何将布尔矩阵的每个元素设置为false而不循环
- 如何在设置元素中重用向量?
- C++:查找并擦除设置元素
- 设置元素的get位置
- 从CHtmlView调用javascript或设置元素焦点