【问题标题】:Counting and removing duplicates in an array c计算和删除数组 c 中的重复项
【发布时间】:2016-02-15 20:38:20
【问题描述】:

假设我有一个包含 [2,4,6,7, 7, 4,4] 的数组 我想要一个可以迭代的程序,然后打印出这样的东西:

Value:     Count:
2          1
4          3
6          1
7          2

我不希望它打印出 ex 4 三次。 到目前为止我得到了什么:

for (int i = 0; i < numberOfInts; i++)
{
    dub[i] = 0;
    for (int y = 0; y < numberOfInts; y++)
    {
        if (enarray[i] == enarray[y])
        {

            dub[i]++;
        }
    }

}

所以基本上我检查数组中的每个元素与所有元素,并且对于每个重复项,我将一个添加到新数组 dub[] 中的索引。 因此,如果我使用上面的示例数组运行此代码,然后将其打印出来,我会得到如下结果: 1,3,1,2,2,3,3。这些是相当混乱的数字,因为我真的不知道它们属于哪些数字。特别是当我将数组中的数字随机化时。然后我必须删除数字,所以我只有一个。谁有更好的解决方案?

【问题讨论】:

  • 你的 char 数组,它是否只包含从 '0' 到 '9' 的字符?
  • 其实我用的是int,现在更新了。
  • 建议保留一个数组 (int numbers[10] = {0}) 然后为源数组中读取的每个值 numbers[[sourceValue]++;然后在打印结果时, for( int x=0;x

标签: c arrays duplicates


【解决方案1】:

您可以在检查每个元素是否重复时遍历数组,在这种情况下,您可以增加它的计数(循环仅检查节省处理时间的值)。这使您无需创建任何额外的缓冲区数组或结构即可完成所需的工作。

bool 'bl' 防止重复打印

int main() {

    int arr[] = { 2, 4, 6, 7, 7, 4, 4 };
    int size = (sizeof(arr) / sizeof(int));

    printf("Value:\tCount\n");
    for (int i = 0; i < size; i++) {
        int count = 0, bl = 1; //or 'true' for print
        //check elements ahead and increment count if repeated value is found 
        for (int j = i; j < size; j++) {
            if (arr[i] == arr[j]) {
                count++;
            }
        }
        //check if it has been printed already
        for (int j = i-1; j >= 0; j--) {
            if (arr[i] == arr[j]) {
                bl = 0; //print 'false'
            }
        }
        if (bl) { printf("%d\t\t%d\n", arr[i], count); } 
    }

    return 0;
}

【讨论】:

  • 缩进坏了,代码不起作用。
  • 我正在努力获得正确的缩进,因为我在手机上,但代码确实有效
  • 如果你修复它,请告诉我。
  • 刚刚做了 ;) 对无意义的代码感到抱歉。我终于打开我的笔记本电脑并检查了它
  • 哦,是的,这是因为索引 j 永远不会为零。我已经修好了
【解决方案2】:

鉴于 char 数组仅包含 '0' 到 '9',您可以使用这样的简单查找表:

#include <stdio.h>

typedef struct
{
    char c;
    int  num;
} TSet;

TSet my_set[] =
{
    { '0', 0 },
    { '1', 0 },
    { '2', 0 },
    { '3', 0 },
    { '4', 0 },
    { '5', 0 },
    { '6', 0 },
    { '7', 0 },
    { '8', 0 },
    { '9', 0 },
};

int main()
{
    char a[] = {'2','4','6','7','7', '4','4'};
    int i;
    for( i = 0; i < sizeof(a) / sizeof(char); i++ )
    {
        my_set[ a[i] - '0' ].num++;
    }

    printf( "%-10s%-10s\n", "Value:", "Count:" );
    for( i = 0; i < sizeof(my_set) / sizeof(TSet); i++ )
    {
        if( my_set[i].num != 0 )
        {
            printf( "%-10c%-10d\n", my_set[i].c, my_set[i].num );
        }
    }
}

输出:

Value:    Count:    
2         1         
4         3         
6         1         
7         2    

【讨论】:

  • 其实我没有用chars,我用ints。对于那个很抱歉。还是用同样的方法解决?
  • 应该是,换类型就好了
  • 让我知道您是否可以使用 int 修改它。我已经成功了。
【解决方案3】:

我不明白这里的复杂性。我认为有两种方法既高效又易于实施:

计数排序

  • 需要数组中最大元素大小的 int 数组
  • 总体复杂度 O(n + m),其中 m 是数组中的最大元素

qsort 和枚举

  • qsort 在 O(n * log(n)) 中工作,并为您提供排序数组
  • 数组排序后,您可以简单地对其进行迭代并计数
  • 整体复杂度 O(n*log(n))

【讨论】:

    【解决方案4】:
    1. 对数组进行排序,通常使用qsort() 函数
    2. 遍历所有元素,连续计数相等的元素,如果检测到下一个不同的元素,则打印前者的计数

    这适用于任何个不同的元素。也不需要第二个数组。

    【讨论】:

    • 如何在 C 中对数组进行排序?
    【解决方案5】:

    你有大致的想法。除了你的输入数组,我建议另外三个数组:

    • 一个used 数组,用于跟踪输入中的哪些条目已被计数。
    • 一个value 数组,用于跟踪input 数组中的不同数字。
    • 一个count 数组,用于跟踪数字出现的次数。

    例如处理输入数组中的2和4后,数组内容为

    input[] = { 2,4,6,7,7,4,4 };
    used[]  = { 1,1,0,0,0,1,1 };  // all of the 2's and 4's have been used
    value[] = { 2,4           };  // unique numbers found so far are 2 and 4
    count[] = { 1,3           };  // one '2' and three '4's
    

    【讨论】:

      【解决方案6】:

      在外层的for循环中放一条打印语句来打印valuerepetition

      for (int i = 0; i < numberOfInts; i++)
      {
          dub[i] = 0;
          for (int y = 0; y < numberOfInts; y++)
          {
              if (enarray[i] == enarray[y])
              {
      
                  dub[i]++;
              }
          }
      printf("%d%d",enarray[i], dub[i]);
      }
      

      【讨论】:

      • 这不是我想要的。
      • @Jullix993 但在您的问题中您要求解决方案,以便您可以知道这些重复属于哪个数字。这就是答案。
      • 当然,我明白你是怎么想的。那么我想要的是带有值和计数的输出。无论如何谢谢
      • @Jullix993 伙计,这将打印值即 enarray[] 并计数即 dub[]
      • 是的,我知道它会如何打印它,但是再看看我写值和计数输出的问题,它不会一样。
      【解决方案7】:

      你的要求很奇怪。通常,我会创建一个包含 2 个成员的结构,例如“number”和“count”。但是,让我们准确地尝试一下您的要求(一维数组,每个数字后跟它的计数):

      int 
         i,
         numberOfInts = 7,
         numberOfDubs = 0,
         enarray[7] = {2,4,6,7,7,4,4},
         dub[14]; // sizeof(enrray) * 2 => maximum number of dubs (if there are no duplicates)
      
      // For every number on enarray
      for(i = 0; i < numberOfInts; i++)
      {
          int jump = 0;
      
          // Check if we have already counted it
          // Only check against pairs: Odds are the dub counter
          for(int d = 0; d < numberOfDubs && !jump; d += 2)
          {
             if(dub[d] == enarray[i])
             {
                jump = 1;
             }
          }
      
          // If not found, count it
          if(!jump)
          {
             // Assign the new number
             dub[numberOfDubs] = enarray[i];
             dub[numberOfDubs + 1] = 1;
      
             // We can begin from 'i + 1'
             for(int y = i + 1; y < numberOfInts; y++)
             {
                if(enarray[i] == enarray[y])
                {
                     dub[numberOfDubs + 1]++;
                }
             }
      
             // Increment dub's counter by 2: number and it's counter
             numberOfDubs += 2;
          }
      }
      
      // Show results
      for(i = 0; i < numberOfDubs; i += 2)
      {
         printf("%d repeated %d time%s\n", dub[i], dub[i + 1], (dub[i + 1] == 1 ? "" : "s"));
      }
      

      【讨论】:

      • 我的问题有什么奇怪的地方?如果使用 struct 是要走的路,那么我肯定可以做到。
      • 没有唯一的答案。是我用结构来做这件事,这将使代码非常干净和结构化;)你想要结构的另一个答案吗?
      • 这很奇怪,因为您要求一个包含数字的一维数组,并且在每个数组之后,它是计数器。我最好不要合并东西:目前还不清楚。但是您可能出于某种未知原因需要这个...
      • 哦,我明白了,我的错。数字的顺序无关紧要,我只是出于某种原因写了它们。
      猜你喜欢
      • 2021-11-08
      • 1970-01-01
      • 2018-06-02
      • 2021-01-23
      • 2019-03-15
      • 2021-02-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多