首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C++ - multiset中计数重复数?

在C++ - multiset中计数重复数?
EN

Stack Overflow用户
提问于 2021-06-13 14:59:02
回答 2查看 737关注 0票数 1

UPD:-

价值实例

 2 3

 3 2

 5 1

对于多集中的所有实例,我希望将计数限制为1。

代码语言:javascript
运行
复制
#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;
    }
    
}

怎么解决这个问题?

EN

回答 2

Stack Overflow用户

发布于 2021-07-05 07:56:19

我的意见是:

在这种情况下,您应该使用std::set<int>,因为这实际上与您的需求相匹配。如果您愿意,还可以使用std::map<int, int>将键映射到出现的次数。

执行部分答复:

你能把这个加到一个完整的答案上,这样我就可以接受这个问题了吗?

我们开始:

只需过滤副本:

代码语言:javascript
运行
复制
#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";
  }
}

输出:

代码语言:javascript
运行
复制
Value 2
Value 3
Value 5

coliru演示

计算发生的次数:

代码语言:javascript
运行
复制
#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";
  }
}

输出:

代码语言:javascript
运行
复制
Value 2 (3 times)
Value 3 (2 times)
Value 5 (1 times)

coliru演示

诀窍是:

如果键尚未存在,std::map::operator[]将插入一个元素。此元素(在本例中为std::pair<const int, unsigned>)是默认初始化的,它授予以{ key, 0 }形式启动的元素。

因此,有两种情况:

  • 关键还在那里: 元素被创建为{ key, 0 },并且值(元素的.second)会立即递增,从而导致{ key, 1 }
  • 关键已经在那里了: 该值(元素的.second)再次递增。

过滤副本的一种变体:

这保持了最初的输入顺序,但消除了重复(通过在一个单独的std::set簿记)。

代码语言:javascript
运行
复制
#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";
  }
}

输出:

代码语言:javascript
运行
复制
Value 5
Value 2
Value 3

coliru演示

诀窍是:

std::set::插入()返回一对iteratorbool

iterator指向集合中的键(插入或已经插入)。bool表示密钥是否已插入(true)或是否已经存在(false)。

另一个窍门是:

只要删除std::vector中发现的每一个副本,就会导致O(n平方)的复杂度更低。

因此,使用两个迭代器,一个用于读取,一个用于写入。因此,未在簿记表中的每个输入值(因此第一次出现)都会被写回,否则就不会。因此,第一次发生的每个值都移到开始处,并附加到第一次发生的前一个值中。此外,iterWrite指向循环之后的最后一个写入元素,并可用于擦除其余的元素(其中包含所有重复的左输入值)。

该算法的复杂度是O(n) -比朴素方法好得多。

顺便说一句。标准算法如果()也是这样做的。

因此,可以用std::remove_if()实现相同的算法。

代码语言:javascript
运行
复制
#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";
  }
}

输出:

如上所示

coliru演示

票数 0
EN

Stack Overflow用户

发布于 2021-07-05 12:32:25

代码语言:javascript
运行
复制
#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;
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67959613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档