UPD:-
价值实例
2 3
3 2
5 1
对于多集中的所有实例,我希望将计数限制为1。
#include<bits/stdc++.h>
using namespace std;
int main() {
multiset<int> p1;
p1.insert(5);
p1.insert(2);
p1.insert(3);
p1.insert(3);
p1.insert(2);
p1.insert(2);
for(auto itr : p1) {
if(p1.count(itr) > 1)
p1.erase(itr);
cout << itr;
}
}
怎么解决这个问题?
发布于 2021-07-05 07:56:19
我的意见是:
在这种情况下,您应该使用
std::set<int>
,因为这实际上与您的需求相匹配。如果您愿意,还可以使用std::map<int, int>
将键映射到出现的次数。
执行部分答复:
你能把这个加到一个完整的答案上,这样我就可以接受这个问题了吗?
我们开始:
只需过滤副本:
#include <iostream>
#include <set>
int main()
{
int sample[] = { 5, 2, 3, 3, 2, 2 };
// add all values at most once
using Table = std::set<int>;
Table table;
for (int value : sample) table.insert(value);
// output the result
for (const Table::value_type& entry : table) {
std::cout << "Value " << entry << "\n";
}
}
输出:
Value 2
Value 3
Value 5
计算发生的次数:
#include <iostream>
#include <map>
int main()
{
int sample[] = { 5, 2, 3, 3, 2, 2 };
// add all values at most once but count the number of occurrences
using Table = std::map<int, unsigned>;
Table table;
for (int value : sample) ++table[value];
// output the result
for (const Table::value_type& entry : table) {
std::cout << "Value " << entry.first << " (" << entry.second << " times)\n";
}
}
输出:
Value 2 (3 times)
Value 3 (2 times)
Value 5 (1 times)
诀窍是:
如果键尚未存在,std::map::operator[]将插入一个元素。此元素(在本例中为std::pair<const int, unsigned>
)是默认初始化的,它授予以{ key, 0 }
形式启动的元素。
因此,有两种情况:
{ key, 0 }
,并且值(元素的.second
)会立即递增,从而导致{ key, 1 }
。.second
)再次递增。过滤副本的一种变体:
这保持了最初的输入顺序,但消除了重复(通过在一个单独的std::set
簿记)。
#include <iostream>
#include <set>
#include <vector>
int main()
{
using Sample = std::vector<int>;
Sample sample = { 5, 2, 3, 3, 2, 2 };
// remove duplicates
using Table = std::set<int>;
Table table;
Sample::iterator iterRead = sample.begin();
Sample::iterator iterWrite = sample.begin();
for (; iterRead != sample.end(); ++iterRead) {
if (table.insert(*iterRead).second) *iterWrite++ = *iterRead;
}
sample.erase(iterWrite, sample.end());
// output the result
for (const Sample::value_type& entry : sample) {
std::cout << "Value " << entry << "\n";
}
}
输出:
Value 5
Value 2
Value 3
诀窍是:
std::set::插入()返回一对iterator
和bool
。
iterator
指向集合中的键(插入或已经插入)。bool
表示密钥是否已插入(true
)或是否已经存在(false
)。
另一个窍门是:
只要删除std::vector
中发现的每一个副本,就会导致O(n平方)的复杂度更低。
因此,使用两个迭代器,一个用于读取,一个用于写入。因此,未在簿记表中的每个输入值(因此第一次出现)都会被写回,否则就不会。因此,第一次发生的每个值都移到开始处,并附加到第一次发生的前一个值中。此外,iterWrite
指向循环之后的最后一个写入元素,并可用于擦除其余的元素(其中包含所有重复的左输入值)。
该算法的复杂度是O(n) -比朴素方法好得多。
顺便说一句。标准算法如果()也是这样做的。
因此,可以用std::remove_if()
实现相同的算法。
#include <algorithm>
#include <iostream>
#include <set>
#include <vector>
int main()
{
using Sample = std::vector<int>;
Sample sample = { 5, 2, 3, 3, 2, 2 };
// remove duplicates
using Table = std::set<int>;
Table table;
Sample::iterator last
= std::remove_if(sample.begin(), sample.end(),
[&](int value) { return !table.insert(value).second; });
sample.erase(last, sample.end());
// output the result
for (const Sample::value_type& entry : sample) {
std::cout << "Value " << entry << "\n";
}
}
输出:
如上所示
发布于 2021-07-05 12:32:25
#include <iostream>
#include <set>
using namespace std;
int main()
{
multiset<int> p1;
p1.insert(5);
p1.insert(2);
p1.insert(3);
p1.insert(4);
p1.insert(2);
p1.insert(2);
for (auto iter = p1.begin(); iter != p1.end();)
{
p1.count(*iter) > 1 ? iter = p1.erase(iter) : iter++;
}
for (auto & iter : p1)
{
cout << iter << ", ";
}
return 0;
}
https://stackoverflow.com/questions/67959613
复制相似问题