Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Определение повторяющихся элементов в массиве


Автор: Firex 30.10.2010, 18:48
Создаётся динамический массив из 10 значений, в него рандомно записываются числа от -10 до 10. Как наиболее рационально можно определить число, которое встречается наибольшее количество раз(и сколько раз конкретно)?
Идея такая, но может быть кто-то предложит рациональнее:
1. Создаём дополнительно структурированный массив вида
Код

struct temp
{
int var
int count
} mass[5]

В var будем писать повторившееся число, а count увеличивать на +1. Далее сортируем mass по переменной count и выводим максимальный элемент. Но тут возникает проблема... если повторившихся элементов несколько и переменная count у них одинаковая... Это лишние операции...

Автор: Annihilator 30.10.2010, 20:05
Первое, что пришло на ум -  2 счетчика завести.
Допустим ты отсортировал массив и получилось что-то типа
1  1  1 2 2 2 2 3 3 3 5 5 7 8 8 9 9 9 9 9 0
первый счетчик начала считать элементы - насчитал 3 по 1
элемент изменился - запускаем второй счетчик по двойкам. Если счетчик по двойкам больше, чем по единицам, присваиваем первому счетчику значение второго счетчика, а второй счетчик используем далее, т.е. для троек. Потом опять сравниваем с первым счетчиком и т.д.

Автор: Firex 30.10.2010, 20:18
Спасибо за идею,если ничего больше не придумаю/не подскажут, то буду так делать.Но вот чувствую, что должно это как-то решаться совсем просто...
З.ы. Хотя этот вариант только для частного примера... хотелось бы масштабный вариант, не только для -10..10.
З.ы.ы. да и рациональности тут не много, имхо )

Автор: Леопольд 30.10.2010, 21:37
Firex, отсортировать и один раз проbежаться по массиву.

Автор: azesmcar 31.10.2010, 08:25
Цитата(Firex @  30.10.2010,  18:48 Найти цитируемый пост)
Создаётся динамический массив из 10 значений, в него рандомно записываются числа от -10 до 10. Как наиболее рационально можно определить число, которое встречается наибольшее количество раз(и сколько раз конкретно)?

есть множество решений, конкретно для этого случае можно хранить дополнительный массив
Код

int r[21] = {0};

потом пройтись по всем элементам и сделать инкремент по индексу равному значению этого элемента +10
Код

for (int i = 0; i < size; ++i)
{
   int element = arr[i];
   ++r[element + 10];
}

в итоге получаешь массив r, в котором по индексу записаны количества повторений каждого элемента массива.
если элементов намного больше то можно использовать std::bitset (правда в этом случае будет невозможно отследить количество повторений) или std::map. 

Автор: Леопольд 31.10.2010, 17:40
Цитата(azesmcar @  31.10.2010,  08:25 Найти цитируемый пост)
потом пройтись по всем элементам и сделать инкремент по индексу равному значению этого элемента +10
Или использовать std::map, значение элемента - ключ.

Но вариант с сортировкой bыстрее.

Автор: Firex 31.10.2010, 17:40
Прошу прощения тех, кто отписался, но я решил всё же пойти по своему алгоритму... Вот только проблемка одна появилась... как на вывод подать только 1 из повторяющихся значений ? А если переменная count одинакова у нескольких переменных, как быть ? Думаю стоит тогда вывести несколько разных переменных по одному разу, у которых переменная count одинакова. Собственно вопрос, что мне делать дальше? Вот код:
Код


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <locale.h>

struct buff // структура для записи переменной и количества совпадений
{
    int tempVar;
    int tempCount;
};
int main(int argc, char *argv[])
{
    setlocale (LC_CTYPE,"");
    srand((int)time(NULL));
    int *mass,i=10,j,t,z;
    char flag;
    struct buff vmass[i];
    mass=calloc(i,sizeof(int)); // динамический массив
    for(j=0;j<i;j++) // заполняем рандомными числами от -10 до 10
    {
        mass[j]=rand()%20-10;
        vmass[j].tempVar=mass[j]; // заносим массив в структурированный массив
        vmass[j].tempCount=0; // для каждой переменной пока количество совпадений 0
        printf("Элемент массива %d случайное число %d\n",j,mass[j]);
    };
    printf("\n");
    for(j=0;j<i;j++)
    {
        flag='f'; // совпадений нет
        t=0;
        for(z=0;z<i;z++)
        {
            if(mass[j]==mass[z]) // если есть совпадение
            {
                flag='t'; // есть совпадение
                t++; // количество совпадений
            };
        };
        if('t'==flag)
        {
            vmass[j].tempCount=vmass[j].tempCount+t; // записываем в структурированный массив количество совпадений
        };
        printf("vmass[%d].tempCount=%d vmass.tempvar=%d\n",j,vmass[j].tempCount,vmass[j].tempVar);
    };
    printf("\n");
    for(j=0;j<i;j++) // сортируем структурированный массив по переменноый Count
    {
        for(z=0;z<i-1;z++)
        {
            if(vmass[z].tempCount<vmass[z+1].tempCount)
            {
                int buff=vmass[z].tempCount;
                vmass[z].tempCount=vmass[z+1].tempCount;
                vmass[z+1].tempCount=buff;
                buff=vmass[z].tempVar;
                vmass[z].tempVar=vmass[z+1].tempVar;
                vmass[z+1].tempVar=buff;
            };
        };
    };
    for(j=0;j<i;j++)
    {
        printf("vmass[%d].tempVar=%d Count=%d\n",j,vmass[j].tempVar,vmass[j].tempCount);
//        if((vmass[j].tempCount==vmass[vmass[j].tempCount-1].tempCount)&&(vmass[j].tempVar==vmass[vmass[j].tempCount-1].tempVar)&&(vmass[j].tempCount<3))

    };
    return 0;
}

Автор: azesmcar 31.10.2010, 17:52
Цитата(Леопольд @  31.10.2010,  17:40 Найти цитируемый пост)
Или использовать std::map, значение элемента - ключ.

я уже писал об этом.

Цитата(Леопольд @  31.10.2010,  17:40 Найти цитируемый пост)
Но вариант с сортировкой bыстрее.

сортировка - O(n log(n))+дальше понадобиться линейный перебор массива для поиска повторений, std::map - просто O(n log(n)), это n вставок, сложность каждой вставки O(log(n)). А в случае с вектором/bitset-ом сложность линейная O(n).

Автор: Леопольд 31.10.2010, 18:00
Код
#include <iostream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

int main()
{
    vector<int> data(100000);

    srand(unsigned (time(NULL)));
    generate(data.begin(), data.end(), rand);

    sort(data.begin(), data.end());

    vector<int>::const_iterator it = data.begin();
    vector<int>::const_iterator end = data.end();

    std::size_t max = 0;
    int num  = *it++;
    std::size_t count = 1;
    int result = num;

    for(;it != end; ++it)
    {
        if(*it != num)
        {
            if(max < count)
            {
                max = count;
                result = num;
            }
            num = *it;
            count = 0;
        }
        ++count;
    }

    cout<<"result = "<<result<<"\nmax = "<<max<<std::endl;

    return 0;
}


Цитата(azesmcar @  31.10.2010,  17:52 Найти цитируемый пост)
я уже писал об этом.
Видимо, невнимательно читаю... smile

Автор: Firex 31.10.2010, 19:37
Подскажите пожалуйста по моему алгоритму smile 

Автор: azesmcar 31.10.2010, 19:52
Firex

Завтра с утра напишу если никто не опередит, сегодня как-то лень smile 

Автор: Леопольд 31.10.2010, 20:11
Цитата(Firex @  31.10.2010,  19:37 Найти цитируемый пост)
Подскажите пожалуйста по моему алгоритму 
Сложно его читать...

Автор: xvr 1.11.2010, 11:53
Цитата(Firex @ 31.10.2010,  19:37)
Подскажите пожалуйста по моему алгоритму smile

Подсказываю - забыть как страшный сон. Из всех, предложенных в этом топике алгоритмов - ваш самый неэффективный (и самый прямолинейный). Единственное преимущество 'самый простой' полностью разбивается стилем реализации, типа 'черт ногу сломит'


Автор: azesmcar 1.11.2010, 12:04
Цитата(xvr @  1.11.2010,  11:53 Найти цитируемый пост)
'черт ногу сломит'

да уж, беглый осмотр кода сразу же отбил всякое желание лезть в эти дебри.

Автор: Firex 1.11.2010, 17:21
Ладно, пусть плохой у меня код... тогда только подскажите дальнейшие действия, если на данной стадии я имею: структурированный массив упорядоченный по переменной vmass.tempCount(число повторений переменной), а в vmass.tempVar лежит сама переменная. Буду премного благодарен.

Автор: xvr 1.11.2010, 18:42
Цитата(Firex @  1.11.2010,  17:21 Найти цитируемый пост)
огда только подскажите дальнейшие действия, если на данной стадии я имею: структурированный массив упорядоченный по переменной vmass.tempCount(число повторений переменной), а в vmass.tempVar лежит сама переменная.

Вывести tempVar из начала (или конца - смотря как у вас они упорядоченны)

Цитата(Firex @  30.10.2010,  18:48 Найти цитируемый пост)
о тут возникает проблема... если повторившихся элементов несколько и переменная count у них одинаковая... 

Не имеет значения - вам же нужен 1 максимальный? Вот один и берите.

Автор: Firex 1.11.2010, 20:01
Решил следующим образом задачу, вдруг кому сгодиться) Программа ищет в массиве число, которое повторяется наибольшее количество раз, если таких чисел несколько, которые имеют равное количество повторений, то выводит их все.
Код


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <locale.h>

struct buff // структура для записи переменной и количества совпадений
{
    int tempVar;
    int tempCount;
};
int main(int argc, char *argv[])
{
    setlocale (LC_CTYPE,"");
    srand((int)time(NULL));
    int *mass,i=10,j,t,z,MaxCount=0;
    char flag;
    struct buff vmass[i];
    mass=calloc(i,sizeof(int)); // динамический массив
    for(j=0;j<i;j++) // заполняем рандомными числами от -10 до 10
    {
        mass[j]=rand()%20-10;
        vmass[j].tempVar=mass[j]; // заносим массив в структурированный массив
        vmass[j].tempCount=0; // для каждой переменной пока количество совпадений 0
        printf("Элемент массива %d случайное число %d\n",j,mass[j]);
    };
    printf("\n");
    for(j=0;j<i;j++)
    {
        flag='f'; // совпадений нет
        t=0;
        for(z=0;z<i;z++)
        {
            if(mass[j]==mass[z]) // если есть совпадение
            {
                flag='t'; // есть совпадение
                t++; // количество совпадений
            };
        };
        if('t'==flag)
        {
            vmass[j].tempCount=vmass[j].tempCount+t; // записываем в структурированный массив количество совпадений
        };
        printf("vmass[%d].tempCount=%d vmass.tempvar=%d\n",j,vmass[j].tempCount,vmass[j].tempVar);
    };
    printf("\n");
    for(j=0;j<i;j++) // сортируем структурированный массив по переменной Var
    {
        for(z=0;z<i-1;z++)
        {
            if(vmass[z].tempVar<vmass[z+1].tempVar)
            {
                int buff=vmass[z].tempVar;
                vmass[z].tempVar=vmass[z+1].tempVar;
                vmass[z+1].tempVar=buff;
                buff=vmass[z].tempCount;
                vmass[z].tempCount=vmass[z+1].tempCount;
                vmass[z+1].tempCount=buff;
            };
        };
        if(MaxCount<vmass[j].tempCount)
        {
            MaxCount=vmass[j].tempCount;
        };
    };
    z=11;
    flag='t';
    if(MaxCount!=1)
    {
        for(j=0;j<i;j++)
        {
//            printf("vmass[%d].tempVar=%d Count=%d\n",j,vmass[j].tempVar,vmass[j].tempCount);
            if((vmass[j].tempVar!=z)&&(vmass[j].tempCount==MaxCount))
            {
                if('t'==flag)
                {
                    printf("Наибольшее чисило раз(%d) встречается элемент %d\n",MaxCount,vmass[j].tempVar);
                    flag='f';
                }
                else if('f'==flag)
                {
                    printf("Элемент %d имеет такое же количество повторений\n",vmass[j].tempVar);
                };
            };
            z=vmass[j].tempVar;
        
        };
    } else printf("Все элементы встречаются по только одному разу/n");
//    printf("MaxCount=%d\n",MaxCount);
    return 0;
}

Пусть код и убогий(как говорят тут старшие товарищи)... зато рабочий и без использования всякой всячины, которая на первом курсе не прокатывает.

Автор: LeD4eG 1.11.2010, 20:05
а нельзя ли сделать приблизительно такое (псевдокод):
Код

max_cnt=0;    //максимальное число повторений одного числа
for(i=0;i<size_mass;i++){
    cnt_var=0;      //счётчик для переменной
    for(j=i+1;j<size_mass-1;j++){
            if(a[j]-a[i]==FLT_EPSILON){
                       cnt_var++;   //увеличиваем счётчик этой переменной
                       k =i               //запоминаем индекс повторяющегося числа
              }
             if(cnt_var>max_cnt) max_cnt=cnr_var;
       }
}

ну хотя я  smile 

Автор: Леопольд 2.11.2010, 12:36
Цитата(Firex @  1.11.2010,  20:01 Найти цитируемый пост)
Пусть код и убогий(как говорят тут старшие товарищи)... зато рабочий и без использования всякой всячины, которая на первом курсе не прокатывает. 
Когда пишешь что-то, надо разбить это что-то на элементарные подзадачи, и оперировать уже ими. Т.е. Заполнил массив - одна функция, отсортировал  - другая, нашёл максимальный элемент(ы) - третья, вывел результат - четвёртая. Потом в main выполнил их по очереди. У тебя же, всё в кучу намешанно, поэтому сложно читать.

Автор: Firex 3.11.2010, 20:26
Леопольд, спасибо, буду это в последующем учитывать. Как то просто не задумывался над этим.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)