【问题标题】:Filter out duplicate values in array in C++在 C++ 中过滤掉数组中的重复值
【发布时间】:2018-05-08 06:13:41
【问题描述】:

我有一排十个数字,例如:

5 5 6 7 5 9 4 2 2 7

现在我想要一个程序,它可以找到所有重复项并在控制台中给出它们,例如 3 乘以 5、2 乘以 2、2 乘以 7。 虽然我确实编写了一种算法,可以在一行数字中找到重复项,但我无法按照描述在控制台中给出它们。我的程序会输出:

3 times 5
2 times 5
2 times 7
2 times 2

我该如何解决这个问题?

#include <iostream>

using namespace std;

int main()
{
  int arr[10];
  int i,j;
  int z = 1;

    for(i = 0; i < 10; i++) {
        cin >> arr[i];
    }
    for(i = 0; i < 10; i++){
        for(j = i+1; j < 10; j++){
            if(arr[i] == arr[j]){
                z++;
            }
        }
        if(z >= 2){
        cout << z << " times " << arr[i] << endl;
        z = 1;
        }

    }


    return 0;
}

【问题讨论】:

  • 创建另一个数组并在满足该索引时增加索引
  • 您必须检查该号码之前是否存在。
  • 你能对数组进行排序或创建额外的结构(如std::map)吗?
  • std::map 是你的朋友。

标签: c++ arrays loops duplicates


【解决方案1】:

您可以在此处使用 STL (C++11):

int arr[10];
std::map<int, int> counters;

for (auto item : arr)
{
    cin >> item;
    ++counters[item];
}

std::for_each(counters.begin(), counters.end(), [](const std::pair<int,int>& item)
{
    if(item.second > 1) std::cout << item.second << " times " << item.first << std::endl;
});

【讨论】:

  • 谢谢,没听懂。编辑了我的答案以包含该约束
【解决方案2】:

您需要检查arr[i] 之前是否尚未找到,例如:

if(z >= 2) {
    int found_before = 0;
    for(j = 0; j < i; ++j)
        if(arr[i] == arr[j])
            found_before = 1;
    if(!found_before)
        cout << z << " times " << arr[i] << endl;
    z = 1;
}

将打印:

3 times 5
2 times 7
2 times 2

这样您就不会再次打印5

使用您的代码,它会打印出 5 次(对于数组中的前 5 个),然后当它移动到数组中的第二个 5 时,它会忘记数组中的前 5 个,并报告它发现 5 两次(本身和数组的第 5 个数字)。

【讨论】:

    【解决方案3】:

    为什么不使用 STL?

    std::map<int, int> counter;
    for (i = 0; i < 10; i++)
            counter[arr[i]] ++;
    for (i = 0; i < 10; i++) {
        if (counter.count(arr[i]) > 0){
            std::cout << counter[arr[i]] << " times "<< arr[i] << std::endl;
            counter.erase(arr[i]);
        }
    }
    

    std::map 是完成这项工作的便捷工具。您可以轻松计算特定数字的出现次数。计数后,您可以打印每个数组元素的计数。使用counter.erase,保证不会多次打印同一个元素。

    【讨论】:

    • if (counter.count(arr[i]) == 0) counter[i] = 1; else 是不需要的。
    • @Jarod42 Absent key 被视为零?
    • m[key] 等价于m.insert(key ValueType{}).second。所以为int创建默认值0。
    • 我可以建议一个更具可读性的for (auto n : arr) ++counter[n]吗?
    • 最后,由于 OP 只想要重复值,&gt;0 应该是 &gt;1,并且遍历映射比遍历数组更合乎逻辑。您甚至可以从中删除所有内容(也许)。
    【解决方案4】:

    为什么要保留你的算法思想,我建议创建子方法:

    std::size_t count(const int* arr, std::size_t start, std::size_t end, int value)
    {
        std::size_t res = 0;
        for (std::size_t i = start; i != end; ++i) {
            if (arr[i] == value) {
                ++res;
            }
        }
        return res;
    }
    

    那么您的固定算法将是:

    for (std::size_t i = 0; i != 10; ++i) {
        if (count(arr, 0, i, arr[i]) != 0) {
            continue; // Already visited
        }
        auto total = count(arr, i, 10, arr[i]);
        if(total >= 2){
            std::cout << z << " times " << arr[i] << std::endl;
        }
    }
    

    【讨论】:

      【解决方案5】:

      一个简单的方法是为它创建另一个数组,特别是如果数字不是那么大。

      假设你已经像这样初始化了你的数组:int nums[10] = { 5, 5, 6, 7, 5, 9, 4, 2, 2, 7 }

      int result[max(nums)]; //Fill with zeroes, max(nums) is the highest number in the array
      for(int i = 0; i < 10; i++) {
          result[nums[i]]++;
      }
      
      for(int i = 0; i < max(nums); i++) {
          if (result[i] > 1) cout << result[i];
      }
      

      请注意,这不是针对内存进行优化的。对于较大数量的内容,您可能需要考虑哈希图。

      【讨论】:

      • 现在计算这个数组:{0, 1, 2, 3, INT_MAX}.
      • 我完全了解这一点,并建议使用哈希图。
      【解决方案6】:

      如果您不需要性能而是需要紧凑的代码,那么带有 std::upper_bound 的 std::multiset 是一种替代方案:

      #include<set>
      #include<iostream>
      #include<algorithm>
      
      int main(int a, char** b)
      {
        int array[] = {5, 5, 6, 7, 5, 9, 4, 2, 2, 7};
      
        std::multiset<int> a(std::begin(array), std::end(array));
        for(auto it = a.begin(); it != a.end(); it = std::upper_bound(a.begin(), a.end(), *it))
        {
          if(a.count(*it) > 1)
              std::cout << *it << " times " << a.count(*it) << std::endl;
        }
      
        return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-30
        • 1970-01-01
        • 2019-01-12
        • 2018-03-21
        • 2017-08-24
        • 1970-01-01
        相关资源
        最近更新 更多