C ++数组(忽略重复数)

时间:2017-11-24 20:37:15

标签: c++ arrays

我是初学程序员,我需要一些帮助。 我需要编写一个程序,从用户读取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;
}

7 个答案:

答案 0 :(得分:0)

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

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

然后从number_of_occurrences到value创建另一个地图。按降序排序。报告第一个值,以及与第一个值一样多的其他值。

答案 1 :(得分:0)

我会尝试给你一些你希望用来纠正你的代码的提示,而不是给你一个解决方案。尝试跟踪以下事项:

  • 记住数组中每个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;   
    }
}

答案 2 :(得分:0)

您遇到问题的原因是,无论何时出现两次或更多次号码,都会打印出来。解决方案是您创建另一个变量maxCount,然后查找数字出现的最大次数。然后循环遍历数组并打印出所有出现最多次数的数字。

希望这有帮助。

杰克

答案 3 :(得分:0)

你可以这样做。在数组中的任何索引处查找该元素的先前出现。如果您发现它是该元素的第一个出现,您只需要查看数组中是否存在该元素的出现。 最后显示频率(此处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]<<" ";
    }
}

答案 4 :(得分:0)

以下是使用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. 原始数组从头到尾迭代(BTW,因为你可以看到它可以是任意长度,而不仅仅是10,因为它使用了开头和结尾的迭代器)。
  2. 我们将在std::count
  3. 中存储我们在std::set找到的重复项
  4. 我们从当前迭代器计算到效率数组结束
  5. 当计数&gt; 1,这意味着我们有一个副本,因此我们将其存储在set中以供参考。
  6. std::set具有唯一键,因此尝试存储set中已存在的其他数字将导致插入.second返回false
  7. 因此,我们只打印唯一的插入,这些插入看起来是出现在数组中的元素的顺序。

答案 5 :(得分:0)

在您的情况下,您可以使用class std::vector来删除元素,调整数组大小......

这是我提供的一个例子,可以产生你想要的东西:

1:将值推入矢量。

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

3-现在,您可以获得临时向量中重复值的向量;您使用2个循环并搜索重复值并从矢量中删除它们。

4-打印输出。

  • 注意:我重载了插入操作符“&lt;&lt;”打印矢量以避免每次使用循环打印矢量元素。

代码可能如下所示:

#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

答案 6 :(得分:0)

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

#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处使用值2,因此它将打印1作为[索引]。

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

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