如何在C++中减少多集中元素的数量
How do I decrease the count of an element in a multiset in C++?
我在c++中使用了一个多集,我相信它存储了一个元素和插入时的相应计数。
这里,当我想删除一个元素时,我只想将该元素在集合中的计数减少1,直到它大于0。
示例C++代码:
multiset<int>mset;
mset.insert(2);
mset.insert(2);
printf("%d ",mset.count(2)); //this returns 2
// here I need an O(1) constant time function (in-built or whatever )
// to decrease the count of 2 in the set without deleting it
// Remember constant time only
-> Function and its specifications
printf("%d ",mset.count(2)); // it should print 1 now .
有什么方法可以实现这一点吗?或者我应该删除它并按要求(count-1)次插入元素2吗?
。。。我在c++中使用了一个多集,它存储一个元素和它各自的计数。。。
不,你不是。您使用的是一个多集,它存储插入n次的值的n个副本。
如果要存储将值与计数相关联的内容,请使用类似std::map<int, int>
的关联容器,并使用map[X]++
来增加X的数量。
。。。我需要一个O(1)常数时间函数。。。减少计数。。。
map
和set
都有O(log N)复杂性,只是为了找到要更改的元素,所以这对它们来说是不可能的。用std::unordered_map
/set
求O(1)的复杂度。
。。。我只想把集合中那个元素的计数减少1,直到它>0
我不知道这意味着什么。
-
带有一个集合:
- 要从集合中删除元素的所有副本,请使用
equal_range
获取一个范围(迭代器对),然后擦除该范围 - 要删除非空范围中除一个副本外的所有副本,只需增加对中的第一个迭代器,并在擦除新范围之前检查它是否仍不等于第二个迭代者
这两者都有一个O(log N)查找(
equal_range
)步骤,然后是一个线性时间擦除步骤(尽管它与具有相同密钥的元素数量而不是N是线性的)。 - 要从集合中删除元素的所有副本,请使用
-
带地图:
- 要从地图中删除计数,只需擦除键
- 要将计数设置为1,只需使用
map[key]=1;
这两者都有一个O(log N)查找,然后是一个恒定的时间擦除
-
有一张无序的地图。。。出于您的目的,它与上面的地图相同,除了O(1)的复杂性。
下面是一个使用unordered_map
:的快速示例
template <typename Key>
class Counter {
std::unordered_map<Key, unsigned> count_;
public:
unsigned inc(Key k, unsigned delta = 1) {
auto result = count_.emplace(k, delta);
if (result.second) {
return delta;
} else {
unsigned& current = result.first->second;
current += delta;
return current;
}
}
unsigned dec(Key k, unsigned delta = 1) {
auto iter = count_.find(k);
if (iter == count_.end()) return 0;
unsigned& current = iter->second;
if (current > delta) {
current -= delta;
return current;
}
// else current <= delta means zero
count_.erase(iter);
return 0;
}
unsigned get(Key k) const {
auto iter = count_.find(k);
if (iter == count_.end()) return 0;
return iter->second;
}
};
并像这样使用:
int main() {
Counter<int> c;
// test increment
assert(c.inc(1) == 1);
assert(c.inc(2) == 1);
assert(c.inc(2) == 2);
// test lookup
assert(c.get(0) == 0);
assert(c.get(1) == 1);
// test simple decrement
assert(c.get(2) == 2);
assert(c.dec(2) == 1);
assert(c.get(2) == 1);
// test erase and underflow
assert(c.dec(2) == 0);
assert(c.dec(2) == 0);
assert(c.dec(1, 42) == 0);
}
相关文章:
- 如何从存储在std::映射中的std::集中删除元素
- 在std::集中获取与给定元素最接近的元素
- 如何查看提升集中<cpp_int>的下一个和上一个元素
- 如何有效地从C++集中删除开始和结束元素
- 如何在 c++ 集中插入元素,直到按下 Enter 键
- 如何检查 O(N) 时间复杂度的多重集中是否有 2 个或更多元素具有相同的值
- 如何在C++中减少多集中元素的数量
- 指针集中元素的顺序
- 从C 中的2D集中删除元素
- 更改STL多集中两个相等元素的顺序
- 如何有效地从std::集中选择随机元素
- 如何遍历两对 STL 集中的所有元素<对<t1,t2>,pair<t1,t2>>?
- 多集是如何工作的,以及如何在多集中找到最小元素
- 如何使迭代器指向与C++集中的另一个元素相同的元素
- 获取C++多集中的前N个元素
- 将连字符作为元素包含在scanf()的扫描集中,如果它是列表中的第一个字符或最后一个字符
- 为什么我不能在 STL 集中插入 600 万个元素?
- 在并集中命名数组元素或结构和数组
- 如何将数组的元素分配给 x86 程序集中的变量
- C++lambda从向量集中移除元素