Frage

Nehmen wir einen Vektor / Matrix in C ++ haben, und wir wünschen, welche dieser N Elemente zählen maximale sich wiederholende Ereignisse und gibt die höchste Zählung hat. Welcher Algorithmus ist am besten für diesen Job geeignet.

Beispiel:

int a = { 2, 456, 34, 3456, 2, 435, 2, 456, 2}

ist der Ausgang 4, weil 2 4-mal auftritt. Das ist die maximale Anzahl der 2 auftritt.

War es hilfreich?

Lösung

Sortieren Sie das Array und macht dann einen schnellen Pass jede Zahl zu zählen. Der Algorithmus hat O (N * log N) Komplexität.

Alternativ erstellen Sie eine Hash-Tabelle, die Nummer als Schlüssel. Lagern Sie in der Hash-Tabelle einen Zähler für jedes Element, das Sie eingegeben haben. Sie werden in der Lage, alle Elemente in einem Durchgang zu zählen; jedoch hängt die Komplexität des Algorithmus nun auf die Komplexität Ihrer Häsing Funktion.

Andere Tipps

Optimiert für Raum:

Quicksort (zum Beispiel) dann über die Elemente iterieren, Spur der größten Zählung hält nur. Allenfalls O (N log N).

Optimiert für Geschwindigkeit:

Iterate alle Elemente über, den Überblick über die getrennten Zählungen zu halten. Dieser Algorithmus wird immer O (n).

Wenn Sie den RAM und Ihre Werte sind nicht zu groß, verwenden Sie sortieren zu zählen.

Eine mögliche C ++ Implementierung, könnte die Verwendung von STL macht:

#include <iostream>
#include <algorithm>
#include <map>

// functor
struct maxoccur
{
    int _M_val;
    int _M_rep;

    maxoccur()
    : _M_val(0),
      _M_rep(0)
    {}

    void operator()(const std::pair<int,int> &e)
    {
        std::cout << "pair: " << e.first << " " << e.second << std::endl;
        if ( _M_rep < e.second ) {
            _M_val = e.first;
            _M_rep = e.second;
        }
    }
};

int
main(int argc, char *argv[])
{
    int a[] = {2,456,34,3456,2,435,2,456,2};
    std::map<int,int> m; 

    // load the map
    for(unsigned int i=0; i< sizeof(a)/sizeof(a[0]); i++) 
        m [a[i]]++;

    // find the max occurence...
    maxoccur ret = std::for_each(m.begin(), m.end(), maxoccur());
    std::cout << "value:" << ret._M_val << " max repetition:" << ret._M_rep <<  std::endl;

    return 0;
}

ein bisschen Pseudo-Code:

//split string into array firts
strsplit(numbers) //PHP function name to split a string into it's components
i=0
while( i < count(array))
 {
   if(isset(list[array[i]]))
    {
      list[array[i]]['count'] = list + 1
    }
   else
    {
      list[i]['count'] = 1
      list[i]['number']
    }
   i=i+1
 }
usort(list) //usort is a php function that sorts an array by its value not its key, Im assuming that you have something in c++ that does this
print list[0]['number'] //Should contain the most used number

Der Hash-Algorithmus (Build Zählung [i] = #occurrences (i) in grundsätzlich linearer Zeit) ist sehr praktisch, ist aber theoretisch nicht streng O (n), weil es Hash-Kollisionen während des Prozesses sein könnte.

Ein interessanter Sonderfall dieser Frage die Mehrheit Algorithmus ist, wo Sie ein Element finden möchten, die n / 2 der Feldeinträge in mindestens vorhanden ist, wenn ein solches Element vorhanden ist.

Hier ist eine kurze Erklärung , und ein ausführlichere Erklärung , wie dies zu tun in lineare Zeit, ohne jede Art von Hash-Verschlagenheit.

Wenn der Bereich der Elemente groß ist im Vergleich mit der Anzahl der Elemente, das würde ich, wie schon andere gesagt haben, nur zu sortieren und scannen. Dies ist zeit n * log n und kein zusätzlicher Platz (vielleicht n zusätzliche log).

Das Problem mit dem Zählen Art ist, dass, wenn der Wertebereich groß ist, kann es mehr Zeit, um die Zählung Array zu initialisieren, als zu sortieren.

Hier ist meine komplette, getestet, Version, eine std::tr1::unordered_map verwendet wird.

Ich mache diese etwa O (n). Erstens iteriert es durch die n Eingabewerte der Zählungen in dem unordered_map einzufügen / aktualisieren, dann ist es eine partial_sort_copy tut, die O (n) ist. 2 * O (n) ~ = O (n).

#include <unordered_map>
#include <vector>
#include <algorithm>
#include <iostream>

namespace {
// Only used in most_frequent but can't be a local class because of the member template
struct second_greater {
    // Need to compare two (slightly) different types of pairs
    template <typename PairA, typename PairB>
    bool operator() (const PairA& a, const PairB& b) const
        { return a.second > b.second; }
};
}

template <typename Iter>
std::pair<typename std::iterator_traits<Iter>::value_type, unsigned int>
most_frequent(Iter begin, Iter end)
{
    typedef typename std::iterator_traits<Iter>::value_type value_type;
    typedef std::pair<value_type, unsigned int> result_type;

    std::tr1::unordered_map<value_type, unsigned int> counts;

    for(; begin != end; ++begin)
        // This is safe because new entries in the map are defined to be initialized to 0 for
        // built-in numeric types - no need to initialize them first
        ++ counts[*begin];

    // Only need the top one at this point (could easily expand to top-n)
    std::vector<result_type> top(1);

    std::partial_sort_copy(counts.begin(), counts.end(),
                           top.begin(), top.end(), second_greater());

    return top.front();
}

int main(int argc, char* argv[])
{
    int a[] = { 2, 456, 34, 3456, 2, 435, 2, 456, 2 };

    std::pair<int, unsigned int> m = most_frequent(a, a + (sizeof(a) / sizeof(a[0])));

    std::cout << "most common = " << m.first << " (" << m.second << " instances)" << std::endl;
    assert(m.first == 2);
    assert(m.second == 4);

    return 0;
}

Es wil in O (n) sein ............ aber die Sache ist die große Nr. von Array ein weiteres Array mit gleicher Größe nehmen kann ............

for (i = 0; i

mar = count [o]; index = o;

for (i = 0; i

dann wird der Ausgang sein ......... das Element Index ist aufgetreten für max nicht. Mal in diesem Array ........

hier a [] ist das Datenfeld, wo wir die max Vorkommen bestimmter nicht suchen müssen. in einem Array .......

count [] mit der Zählung jedes Elements .......... Hinweis: Wir alrdy der Bereich von Daten knw in Array sein .. sagen für zB. Die Daten in diesem Array liegen im Bereich von 1 bis 100 ....... dann die Zählung Array mit 100 Elementen haben, um zu verfolgen, wenn sie den indexierten Wert um eins aufgetreten increament ........

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top