【问题标题】:Count the number of repeating elements in an array计算数组中重复元素的数量
【发布时间】:2020-12-01 18:53:17
【问题描述】:

问题是计算给定数组中重复元素的数量:

假设输入是:

  • 1
1 2 3 3 3
  • 2
1 2 2 3 3 3 4 5

那么第一个输入的输出应该是 3,第二个输入应该是 5。

我已经编写了代码,根据逻辑,它的输出应该是 3,但我得到的输出是 5,任何人都可以发现错误。

#include <bits/stdc++.h>

using namespace std;

int main() {
  int a[5] = {
    1,
    4,
    2,
    4,
    4
  };
  int b[101];
  memset(b, 0, 101);
  int cp = 0, i = 0;
  b[a[i]] = 1;

  for (int j = i + 1; j < 5; j++) {

    if (b[a[j] > 0]) {
      if (b[a[j]] == 1)
        cp++;
      cp++;
      b[a[j]]++;
    } else
      b[a[j]] = 1;

  }
  cout << cp;

  return 0;
}

【问题讨论】:

  • memset(b,0,101) 不会将整个数组归零,如果 a 中的值大于 25,则会导致未定义的行为。int b[101] = {}; 可以避免这个问题。

标签: c++ arrays hash


【解决方案1】:

您的代码中有一个错字 - 您写的是 if(b[a[j]&gt;0]) 而不是 if (b[a[j]] &gt; 0),这会产生完全不同的行为。

为避免此类错误,您应该正确格式化代码并为变量指定有意义的名称。例如,您的 main 函数可以重写为:

int main() {
    const size_t SIZE = 5;
    int a[SIZE] = {1, 4, 2, 4, 4};
    const int MAX_VALUE = 100;
    int count[1 + MAX_VALUE] = {};
    int duplicates = 0;

    for (int j = 0; j < SIZE; j++) {
        if (count[a[j]] > 0)
            duplicates++;
        if (count[a[j]] == 1)
            duplicates++;

        count[a[j]]++;
    }

    cout << duplicates;
}

请注意,我还删除了第一个数组元素的特殊情况 - 这是不必要的,而且经常容易出错。

【讨论】:

    【解决方案2】:

    如果我读到类似的东西

    #include <bits/stdc++.h>
    using namespace std;
    

    和变量名,那么我假设这个问题与一些竞争性编程网站有关。所以,我的猜测是还有更多我们不知道的限制。例如,我们在这里看到了幻数 101。也许有一个约束,我们只有 0..100 范围内的整数。反正我们也不知道。

    我想展示一个 C++ 解决方案。基本上,这是使用std::mapstd::unordered_map 计数项目的标准方法。

    请看下面的代码,它基本上由两行组成。后面我会解释:

    #include <iostream>
    #include <vector>
    #include <unordered_map>
    #include <numeric>
    
    std::vector testData{ 1,4,2,4,4 };
    
    int main() {
    
        std::unordered_map<int, size_t> counter{};
    
        // Count the occurence of each integer value
        for (const int i : testData) counter[i]++;
    
        // Accumulate repeating values and show result
        std::cout << std::accumulate(counter.begin(), counter.end(), 0U, [](size_t c, const auto& p) { return c+(p.second > 1 ? p.second : 0U); });
    
        return 0;
    }
    

    如前所述,我们使用地图的标准方法。这里的重点是理解地图的索引运算符。请参阅here。并阅读:

    返回对映射到与 key 等效的键的值的引用,如果这样的键不存在,则执行插入。

    重要的一点是:如果它已经在映射中,它将返回对值的引用。如果不是,它将在映射中创建值并再次返回对该值的引用。而且因为我们以任何方式获得了对该值的引用,所以我们可以简单地递增它。

    在我们通过一个非常简单的 for 循环对来自“testData”向量的所有源值执行此操作后,我们就有了所有值的计数。如果一个值的计数大于 1,则它是重复的或“重复的”。

    因此,我们只需要累加所有大于 1 的计数器。为此,我们使用专用函数 std::accumulate

    如果您有任何问题,请提出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-20
      • 2020-02-01
      • 2021-12-22
      • 2016-04-21
      • 1970-01-01
      相关资源
      最近更新 更多