【问题标题】:C++ Array (disregarding a repeat number)C++ 数组(忽略重复编号)
【发布时间】:2018-05-08 20:22:50
【问题描述】:

我是一名初级程序员,我需要一些帮助。 我需要编写一个程序,从用户那里读取一个由 10 个数字组成的数组,然后对其进行扫描并找出数组本身中最常见的数字并打印出来。如果数组中只有一个公共数字,则只打印该数字。但是,如果有不止一个数字出现不止一次,也按照它们在数组中出现的顺序打印它们。 例如 - 1 2 3 3 4 5 6 7 8 9 - 输出为 3 For- 1 2 3 4 1 2 3 4 5 6 - 输出为 1 2 3 4 for- 1 1 1 1 2 2 2 3 3 4 - 输出为 1 2 3

现在,我遇到的问题是,每当我有一个重复两次以上的数字时(参见上面的第三个示例),我得到的输出就是该数字的循环迭代次数而不仅仅是那个数字一次。 欢迎任何帮助。

代码附在下面-

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int array [10], index, checker, common;
main ()
{

        for (index=0; index<10; index++)
        {
            cin >> array [index];
        }

        for (index=0; index<10; index++)
            {
                int tempcount=0;
                for (checker=(index+1);checker<10;checker++)
                    {   
                        if (array[index]==array[checker])
                            tempcount++;
                    }
                   if (tempcount>=1)
                   cout << array[index]<<" ";

            }

    return 0;
}

【问题讨论】:

  • 问题在于您的算法只检查在当前实例之后是否存在该值的另一​​个实例,这归结为找到不是最后一个值的每个实例。
  • 完全正确。这就是我想要弄清楚的
  • 想想你的代码在做什么。如果一个值出现 3 次,外部循环将遇到它 3 次。第一次,内部循环会将tempcount 计算为2 并打印该值。第二次,tempcount 将计算为1,因此将再次打印该值。为了解决这个问题,您需要以某种方式记录以前打印过的值,以便不再打印它们。

标签: c++ arrays


【解决方案1】:

为任务使用适当的数据结构。

创建一个将值映射到 number_of_occurrences 的 std::unordered_map,并对输入数据进行一次传递。

然后创建另一个从 number_of_occurrences 到 value 的映射。将其排序,按降序排列。报告第一个值,以及与第一个值一样多次出现的任何其他值。

【讨论】:

  • 感谢您的快速回答,但我仍然是初学者。我不知道哈希是什么...抱歉,谢谢
  • 好的,好的,创建一个值数组 --> num_occur 条目,以及另一个 num_occur 数组 --> 值条目。一样的,只是慢了点。或者通过通过查找最大 num_occur 来解决第二步,然后通过另一遍来报告具有该最大值的所有条目。或者,采取不同的策略,对输入列表进行排序。然后是第一次通过测量相同值的运行长度(并记住最大运行长度),第二次通过报告具有该最大运行长度的所有运行。
  • 如果它还包含一个示例,这将是一个很好的答案。请注意,地图是隐式排序的。要求对地图进行排序是多余的。或许std::max_element 可以代替转置初始映射。
【解决方案2】:

您遇到问题的原因是,只要一个数字出现两次或多次,就会打印出来。一个解决方案是创建另一个变量 maxCount,然后找到一个数字出现的最大次数。然后循环遍历数组,打印出出现次数最多的所有数字。

希望这会有所帮助。

杰克

【讨论】:

    【解决方案3】:

    我不会给您写一个解决方案,而是尝试给您一些提示,希望您可以使用这些提示来纠正您的代码。尝试跟踪以下内容:

    • 记住数组中每个distinct 数字第一次出现的位置。
    • 计算每个数字出现的次数

    将两者结合起来得到你的解决方案。

    编辑:

    int array[] = {1, 2, 3, 4, 1, 2, 3, 4, 5, 6};
    
    int first [11], cnt[11];
    
    for(int i = 0; i < 11; i++){
        first[i] = -1;
        cnt[i] = 0;
    }
    
    int max = 0;
    
    for(int i = 0; i < 10; i++){
        cnt[array[i]]++;
        if(max < array[i]) max = array[i];
    }   
    
    for(int i = 0; i <= max; i++){
        if(cnt[i] > 1 && first[i] == -1) {
            printf(" %d", i);
            first[i] = i;   
        }
    }
    

    【讨论】:

    • 感谢您的回答。您是指使用第二个数组来保存不同的数字吗?
    • Np,如果有帮助,请告诉我们。是的,您应该有 2 个数组,一个保留该数字第一次出现的位置,另一个保留该数字的出现次数。
    • 还在苦苦挣扎:/建议?
    • 如果用户输入的数字大于10怎么办?
    • 很容易根据需要调整数组大小。我刚刚解决了那里的一个例子。
    【解决方案4】:

    你可以做这样的事情。在数组中的任何索引处查找该元素的先前出现。如果你发现它是该元素的第一次出现,你只需要查看数组中是否有该元素的出现。 最后显示频率(此处为num)大于1的元素。

    for (int i = 0; i < 10; i++)
    {
        int presentBefore = 0;
        for (int j = 0; j < i; j++) //if any previous occurence of element
        {
            if (array[i] == array[j]) presentBefore++;
        }
    
        if (presentBefore == 0)//if first occurence of the element
        {
            int num = 1;
            for (int j = i + 1; j < 8; j++)// if occurences ahead in the array
            {
              if (array[i] == array[j]) num++;
            }
            if(num>1)cout<<array[i]<<" ";
        }
    }
    

    【讨论】:

      【解决方案5】:

      这是另一个使用STLstd::set 的解决方案。

      #include <iostream>
      #include <algorithm>
      #include <set>
      #include <iterator>
      
      int main()
      {
      
          int array[12] = { 1, 2, 3, 1, 2, 4, 5, 6, 3, 4, 1, 2 };
          std::set<int> dupes;
      
          for (auto it = std::begin(array), end = std::end(array); it != end; ++it)
          {
              if (std::count(it, end, *it) > 1 && dupes.insert(*it).second)
                  std::cout << *it << " ";
          }
      
          return 0;
      }
      

      打印:

      1 2 3 4
      

      我将尝试解释这是如何工作的:

      1. 原始数组从头到尾迭代(顺便说一句,您可以看到它可以是任意长度,而不仅仅是 10,因为它使用了开始和结束的迭代器)
      2. 我们将在std::set 中存储使用std::count 找到的重复项
      3. 为了提高效率,我们从当前迭代器开始计数直到数组末尾
      4. 当 count > 1 时,这意味着我们有一个副本,因此我们将其存储在 set 中以供参考。
      5. std::set 具有唯一键,因此尝试存储另一个已存在于 set 中的数字将导致插入 .second 返回 false
      6. 因此,我们只打印唯一的插入,它们似乎按照数组中出现的元素顺序。

      【讨论】:

        【解决方案6】:

        在您的情况下,您可以使用class std::vector,它允许您擦除元素、调整数组大小...

        这是我提供的一个示例,它可以产生您想要的结果:

        1:将值推送到向量中。

        2:使用 2 个循环并比较元素 array[i]array[j],如果它们相同,则将 element j 推入新向量。索引j 始终等于i + 1,以避免将值与自身进行比较。

        3- 现在你得到了临时向量中重复值的向量;您使用 2 个循环并搜索重复值并将它们从向量中删除。

        4- 打印输出。

        • 注意:我重载了插入运算符“

        代码可能如下所示:

        #include <iostream>
        #include <vector>
        
        
        std::ostream& operator << (std::ostream& out, std::vector<int> vecInt){
            for(int i(0); i < vecInt.size(); i++)
                out << vecInt[i] << ", ";
            return out;
        }
        
        
        
        int main() {
        
            std::vector< int > vecInt;
            //1 1 1 1 2 2 2 3 3 4 
            vecInt.push_back(1);
            vecInt.push_back(1);
            vecInt.push_back(1);
            vecInt.push_back(1);
            vecInt.push_back(2);
            vecInt.push_back(2);
            vecInt.push_back(2);
            vecInt.push_back(3);
            vecInt.push_back(3);
            vecInt.push_back(4);
        
            std::vector<int> vecUniq;
        
            for(int i(0); i < vecInt.size(); i++)
                for(int j(i + 1); j < vecInt.size(); j++)
                    if(vecInt[i] == vecInt[j])
                        vecUniq.push_back(vecInt[j]);
        
                    std::cout << vecUniq << std::endl;
        
            for(int i = 0; i < vecUniq.size(); i++)
                for(int j = vecUniq.size() - 1 ; j >= 0 && j > i; j--)
                    if(vecUniq[i] == vecUniq[j])
                        vecUniq.erase(&vecUniq[j]);
        
                    std::cout << vecUniq << std::endl;
        
        
            std::cout << std::endl;
            return 0;
        
        }
        
        
        The input:    1 2 3 3 4 5 6 7 8 9 
        The output:   3
        
        The input:    1 2 3 4 1 2 3 4 5 6
        The output:   1 2 3 4
        
        The input:    1 1 1 1 2 2 2 3 3 4
        The output:   1 2 3
        

        【讨论】:

          【解决方案7】:

          对于这个问题,你可以使用一个标记数组来计算你访问一个数字的次数,就像计数排序一样。让我们先看看程序:

          #include <iostream>
          using namespace std;
          
          int print(int a[],int b[])
          {
              cout<<"b :: ";
              for (int index=0;index<10;index++)
              {
                  cout<<b[index]<<"  ";
              }
              cout<<endl;
          }
          
          int main ()
          {
              int a[10],b[11], index, checker, common;
                  for (index=0; index<10; index++)
                  {
                      cin >> a [index];
                      b[index] = 0;
                  }
                  b[10] =0;
          
                  for (index=0;index<10;index++)
                  {
          
                      b[a[index]]++;
                      if (b[a[index]] == 2)
                          cout<<a[index];
                      //print(a,b);
                  }
          
              return 0;
          }
          

          如您所见,我使用数组 b 作为标记数组,它计算一个数字被访问的时间。 数组 b 的大小取决于您要输入的最大数字是多少,我已将数组 b 的大小设置为长度 10,b[11] 因为您的最大数字是 10。索引 0 没有用,但您不必担心它,因为在您的输入为 0 之前它不会被指向。

          最初 b 中数组中的所有元素都设置为 0。 现在假设您的输入是 :: 1 2 3 4 1 2 3 4 5 6

          现在可以在每次迭代后通过取消对打印函数行的注释来检查 b 的值::

          b :: 0  1  0  0  0  0  0  0  0  0     ....1
          b :: 0  1  1  0  0  0  0  0  0  0     ....2
          b :: 0  1  1  1  0  0  0  0  0  0     ....3
          b :: 0  1  1  1  1  0  0  0  0  0     ....4
          b :: 0  2  1  1  1  0  0  0  0  0     ....5
          b :: 0  2  2  1  1  0  0  0  0  0     ....6
          b :: 0  2  2  2  1  0  0  0  0  0     ....7
          b :: 0  2  2  2  2  0  0  0  0  0     ....8
          b :: 0  2  2  2  2  1  0  0  0  0     ....9
          b :: 0  2  2  2  2  1  1  0  0  0     ....10
          

          在第 5 行中,您可以在索引 1 处的 b 的值为 2,因此它将打印 1,即 a[index]。

          并且数组a的元素只有在第一次重复时才会被打印出来,因为这行if(b[a[index]] == 2)

          这个程序使用计数排序的思想,所以如果你愿意,你可以检查计数排序。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-08-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多