web-dev-qa-db-de.com

Finden Sie das Majoritätselement im Array

Das Majoritätselement ist das Element, das mehr als die Hälfte der Größe des Arrays aufweist.

Wie finde ich das Majoritätselement in einem Array in O(n)?

Beispieleingabe:

{2,1,2,3,4,2,1,2,2}

Erwartete Ausgabe:

2
47
Ali Tarhini

Das Mehrheitselement (falls vorhanden) ist auch der Median. Wir können den Median in O(n) finden und dann überprüfen, ob er tatsächlich ein gültiges Mehrheitselement in O (n) ..__ ist. Weitere Details zur Implementierung link

25
Axn
// returns -1 if there is no element that is the majority element, otherwise that element

// funda :: if there is a majority element in an array, say x, then it is okay to discard 
// a part of that array that has no majority element, the remaining array will still have
// x as the majority element

// worst case complexity :  O(n)

int findMajorityElement(int* arr, int size) { 
    int count = 0, i, majorityElement;
    for (i = 0; i < size; i++) {
        if (count == 0)
            majorityElement = arr[i];
        if (arr[i] == majorityElement) 
            count++;
        else
            count--;
    }
    count = 0;
    for (i = 0; i < size; i++)
        if (arr[i] == majorityElement)
            count++;
    if (count > size/2)
        return majorityElement;
    return -1;
}
105
Hitesh Gupta

Es ist traurig zu sehen, dass niemand in fünf Jahren eine angemessene Erklärung für dieses Problem verfasst hat.

Dies ist ein Standardproblem bei Streaming-Algorithmen (bei denen Sie über einen riesigen (potenziell unendlichen) Datenstrom verfügen), und Sie müssen einige Statistiken aus diesem Stream berechnen, die diesen Stream einmal durchlaufen.


Natürlich können Sie es mit Hashing oder Sortierung ansprechen, aber mit einem potenziell unendlichen Stream können Sie den Speicher deutlich überschreiten. Also muss man hier etwas schlau machen.


Das Majoritätselement ist das Element, das mehr als die Hälfte der Größe des Arrays vorkommt. Dies bedeutet, dass das Majoritätselement mehr auftritt als alle anderen Elemente zusammen. Das heißt, wenn Sie zählen, wie oft das Majoritätselement erscheint, und die Anzahl der Vorkommen aller anderen Elemente abziehen, erhalten Sie eine positive Anzahl.

Wenn Sie also die Vorkommen eines Elements zählen und die Anzahl der Vorkommen aller anderen Elemente subtrahieren und die Zahl 0 erhalten, kann Ihr ursprüngliches Element kein Mehrheitselement sein. Dies ist die Basis für einen korrekten Algorithmus:

Deklarieren Sie zwei Variablen, counter und possible_element. Wiederholen Sie den Stream, wenn der Zähler 0 ist - überschreiben Sie das mögliche Element, und initialisieren Sie den Zähler, wenn die Anzahl mit dem möglichen Element identisch ist. Erhöhen Sie den Zähler, andernfalls verringern Sie ihn. Python-Code:

def majority_element(arr):
    counter, possible_element = 0, None
    for i in arr:
        if counter == 0:
            possible_element, counter = i, 1
        Elif i == possible_element:
            counter += 1
        else:
            counter -= 1

    return possible_element

Es ist klar zu sehen, dass der Algorithmus O(n) mit einer sehr kleinen Konstanten vor O(n) (wie 3) ist. Es sieht auch so aus, als wäre die Platzkomplexität O(1), weil wir nur drei Variablen initialisiert haben. Das Problem ist, dass eine dieser Variablen ein Zähler ist, der potenziell auf n anwachsen kann (wenn das Array aus denselben Zahlen besteht). Und um die Nummer n zu speichern, benötigen Sie O(log (n)) Platz. Aus theoretischer Sicht ist O(n) Zeit und O(log(n)) Raum. Praktisch, Sie können 2 ^ 128 Zahlen in einen langen Zeitraum einfügen, und diese Anzahl von Elementen im Array ist unvorstellbar groß.

Beachten Sie auch, dass der Algorithmus nur funktioniert, wenn ein Mehrheitselement vorhanden ist. Wenn ein solches Element nicht vorhanden ist, wird immer noch eine Zahl zurückgegeben, was sicherlich falsch ist. (Der Algorithmus kann leicht geändert werden, um festzustellen, ob das Mehrheitselement vorhanden ist.)

Verlaufskanal: Dieser Algorithmus wurde 1982 irgendwo von Boyer, Moore erfunden und Boyer-Moore-Mehrheitswahlalgorithmus

32
Salvador Dali

Mehrheitselement:

Ein Majoritätselement in einem Array A [] der Größe n ist ein Element, das mehr als n/2 mal erscheint (und daher gibt es höchstens ein solches Element).

Einen Kandidaten finden:

Der Algorithmus für die erste Phase, der in O(n) funktioniert, ist als Moore's Voting Algorithm bekannt. Die Grundidee des Algorithmus ist, wenn wir jedes Vorkommen eines Elements e mit allen anderen Elementen, die sich von e unterscheiden, auslöschen, dann existiert e bis zum Ende, wenn es ein Majoritätselement ist.

findCandidate(a[], size)
1.  Initialize index and count of majority element
     maj_index = 0, count = 1
2.  Loop for i = 1 to size – 1
    (a)If a[maj_index] == a[i]
        count++
    (b)Else
        count--;
    (c)If count == 0
        maj_index = i;
        count = 1
3.  Return a[maj_index]

Der obige Algorithmus durchläuft jedes Element und führt einen Zählerstand von [maj_index]. Wenn nächstes Element gleich ist, wird der Zählerstand erhöht, wenn nächstes Element nicht gleich ist, wird der Zählerwert verringert, und wenn der Zählerstand 0 erreicht, ändert sich der maj_index in den aktuellen Wert Element und Mengen zählen auf 1 . Der First-Phase-Algorithmus gibt uns ein Kandidatenelement. In der zweiten Phase müssen wir prüfen, ob der Kandidat wirklich ein Mehrheitselement ist.

Zweite Phase ist einfach und kann leicht in O (n) ausgeführt werden. Wir müssen nur prüfen, ob die Anzahl des Kandidatenelements größer als n/2 ist. 

Lesen Sie geeksforgeeks für weitere Details

15
Aditya

Zeit läuft)

Raum: O (n)

Gehen Sie durch den Baum und zählen Sie das Vorkommen von Elementen in einer Hashtabelle.

Zeit: O (n lg n) oder O (n * m) (abhängig von der verwendeten Sortierung)

raum: (1)

sortiere das Array und zähle die Vorkommen der Elemente.

Die richtige Antwort auf das Interview: Moore's Voting Algorithm

Zeit läuft)

Raum: O (1)

Gehen Sie die Liste durch, und vergleichen Sie die aktuelle Nummer mit der aktuellen besten Schätzzahl. Wenn die Anzahl gleich der aktuellen Bestschätzungszahl ist, erhöhen Sie einen Zähler. Andernfalls verringern Sie den Zähler. Wenn der Zähler auf Null fällt, ersetzen Sie die aktuelle Bestschätzungsnummer durch die aktuelle Zahl und setzen Sie den Zähler auf 1. Wenn Sie den Strom beenden Am besten ist die Kandidatennummer. Gehen Sie die Liste erneut durch, indem Sie die Instanzen des Kandidaten zählen. Wenn die endgültige Zählung größer als n/2 ist, ist dies die Mehrheit, ansonsten gibt es keine.

3
stonemetal

Im Monte-Carlo-Algorithmus,

Majority (a,n)
//a[]-array of 'n' natural numbers
 {
  j=random(0,1,....,n-1)
  /*Selecting the integers at random ranging from 0 to n-1*/
  b=a[j];c=0;
  for k from 0 to n-1 do
   { 
    if a[k]=b then,
    c=c+1;
    }
    return (c>n/2)
   }
2

Wie wäre es mit einem Stichprobenverfahren? Sie könnten beispielsweise sqrt (n) -Elemente und für jedes Element, das mehr als sqrt (n)/4-mal aufgetreten ist, abtasten (kann naiv in O(n) time und O(sqrt(n)) (Leerzeichen) können Sie prüfen, ob es sich um ein Majoritätselement in der Zeit O(n) handelt.

Dieses Verfahren ermittelt die Mehrheit mit hoher Wahrscheinlichkeit, da das Majoritätselement erwartungsgemäß mindestens 2 mal (n)/2-mal mit einer Standardabweichung von höchstens n ^ {1/4}/2 abgetastet würde.

Eine andere Stichprobenmethode, die einer Methode ähnelt, die ich in einer der doppelten Verknüpfungen gesehen habe, besteht darin, zwei Stichproben zu zeichnen. Wenn sie gleich sind, müssen Sie überprüfen, ob Sie das Majoritätselement in der Zeit O(n) gefunden haben. Der zusätzliche Überprüfungsschritt ist notwendig, da die anderen Elemente außer der Mehrheit nicht eindeutig sind.

2
jonderry

Um die Mehrheit eines Elements in einem Array zu ermitteln, können Sie den Majority Vote Algorithm von Moore verwenden, der einer der besten Algorithmen dafür ist.

Zeitkomplexität:O(n) or linear time

Raumkomplexität:O(1) or constant space

Lesen Sie mehr unter Moores Mehrheitswahlalgorithmus und GeeksforGeeks

1
Deepak Chawla

Eine modifizierte Version des Boyer-Algorithmus 

  • 3 Durchläufe wobei
    • Im ersten Durchlauf führen wir eine Vorwärtsiteration des Arrays durch
    • Im zweiten Durchlauf führen wir eine umgekehrte Iteration des Arrays durch.
    • Im dritten Durchlauf erhalten Sie die Zählungen für die Mehrheitselemente, die im ersten und zweiten Durchgang erhalten wurden.

Technisch ein linearer Komplexitätsalgorithmus (O (3n)) . Ich glaube, dass dies für ein Array mit einem Majoritätselement funktionieren sollte, das mindestens n/2 mal auftritt.

#include <iostream>
#include <vector>

template <typename DataType>
DataType FindMajorityElement(std::vector<DataType> arr) {
    // Modified BOYERS ALGORITHM with forward and reverse passes
    // Count will stay positive if there is a majority element
    auto GetMajority = [](auto seq_begin, auto seq_end) -> DataType{
        int count = 1;
        DataType majority = *(seq_begin);
        for (auto itr = seq_begin+1; itr != seq_end; ++itr) {
            count += (*itr == majority) ? 1 : -1;
            if (count <= 0) {   // Flip the majority and set the count to zero whenever it falls below zero
                majority = *(itr);
                count = 0;
            }
        }
        return majority;
    };
    DataType majority1 = GetMajority(arr.begin(), arr.end());
    DataType majority2 = GetMajority(arr.rbegin(), arr.rend());
    int maj1_count = 0, maj2_count = 0;
    // Check if any of the the majority elements is really the majority
    for (const auto& itr: arr) {
        maj1_count += majority1 == itr ? 1 : 0;
        maj2_count += majority2 == itr ? 1 : 0;
    }
    if (maj1_count >= arr.size()/2)
        return majority1;
    if (maj2_count >= arr.size()/2)
        return majority2;
    // else return -1
    return -1;
}

Code hier getestet

0
blueskin

Verwenden Sie Divide and Conquer, um das Mehrheitselement zu finden. Wenn wir das Array in zwei Hälften teilen, sollte das Mehrheitselement eine Mehrheit in einer der Hälften sein. Wenn wir fortfahren und die Sub-Arrays kombinieren, können wir herausfinden, ob das Mehrheitselement auch die Mehrheit des kombinierten Arrays ist. Dies hat O (nlogN) -Komplexität.

Hier ist eine C++ Implementierung:

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

using std::vector;

// return the count of elem in the array
int count(vector <int> &a, int elem, int low, int high)
{
    if (elem == -1) {
        return -1;
    }

    int num = 0;
    for (int i = low; i <= high; i++) {
        if (a[i] == elem) {
            num++;
        }
    }

    return num;
}

// return the majority element of combined sub-array. If no majority return -1
int combined(vector <int> &a, int maj1, int maj2, int low, int mid, int high)
{
    // if both sub arrays have same majority elem then we can safely say
    // the entire array has same majority elem.
    // NOTE: No majority ie. -1 will be taken care too
    if (maj1 == maj2) {
        return maj1;
    }

    // Conflicting majorities
    if (maj1 != maj2) {
        // Find the count of each maj1 and maj2 in complete array
        int num_maj1 = count(a, maj1, low, high);
        int num_maj2 = count(a, maj2, low, high);
        if (num_maj1 == num_maj2) {
            return -1;
        }
        int half = (high - low + 1) / 2;
        if (num_maj1 > half) {
            return maj1;
        } else if (num_maj2 > half) {
            return maj2;
        }
    }
    return -1;
}

// Divide the array into 2 sub-arrays. If we have a majority element, then it
// should be a majority in at least one of the half. In combine step we will
// check if this majority element is majority of the combination of sub-arrays.
// array a and low is lower index and high is the higher index of array
int get_majority_elem(vector<int> &a, int low, int high)
{
  if (low > high) return -1;
  if (low == high) return a[low];

  int mid = (low + high) / 2;

  int h1 = get_majority_elem(a, low, mid);
  int h2 = get_majority_elem(a, mid + 1, high);

  // calculate the majority from combined sub arrays
  int me = combined(a, h1, h2, low, mid, high);
  return me;
}

0
anubhavr

// Nehmen wir an, wir haben ein Array A . // Wenn wir alle Elemente im angegebenen Array haben und jedes Element weniger als K ist, können wir ein zusätzliches Array B mit der Länge K + 1 erstellen.

// Initialisiere den Wert an jedem Index des Arrays mit 0. // Durchlaufe dann das angegebene Array A, für jeden Arraywert A [i] den Wert mit 1 am entsprechenden Index A [i] in erhöhen das erzeugte Array B. 

// Nach dem Durchlaufen des Arrays A durchlaufen Sie nun das Array B und finden den maximalen Wert. Wenn Sie feststellen, dass der Wert größer als n/2 ist, geben Sie diesen bestimmten Index zurück.

// Zeitkomplexität ist O (n + K), wenn K <= n, dann äquivalent zu O (n).

// Wir haben hier eine Einschränkung, dass alle Elemente des Arrays O (K) sind. // Angenommen, jedes Element ist kleiner oder gleich 100, ist K in diesem Fall 100.

import javax.print.attribute.standard.Finishings;
public class MajorityElement {

    private static int maxElement=100;

    //Will have all zero values initially
    private static int arrB[]=new int[maxElement+1];
    static int findMajorityElement(int[] arrA) { 
         int count = 0, i, majorityElement;
         int n=arrA.length;
         for (i = 0; i < n; i++) {
             arrB[arrA[i]]+=1;
         }

         int maxElementIndex=1;
         for (i = 2; i < arrB.length; i++){
             if (arrB[i]>n/2) {
                maxElementIndex=i;
                break;
            }
        }
        return maxElementIndex;
    }`

    public static void main(String[] args) {
         int arr[]={2,6,3,2,2,3,2,2};
         System.out.println(findMajorityElement(arr));
    }
}
0
Avi
public class MajorityElement {

   public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    int testCases = sc.nextInt();
    while(testCases-- > 0) {
        int n = sc.nextInt();
        int a[] = new int[n];
        int maxCount = 0;
        int index = -1;
        for(int i = 0 ; i < n; i++) {
            a[i] = sc.nextInt();
        }
        for(int i = 0; i < n; i++) {
            int count =0;
            for(int j = 0; j < n; j++) {
                if(a[i] == a[j])
                    count++;
            }
            if(count > maxCount) {
                maxCount = count;
                index = i;
            }
        }
        if(maxCount > n/2)
            System.out.println(a[index]);
        else
            System.out.println(-1);
    }
    sc.close();
   }

}
0

Dies hilft Ihnen und wenn zwei Elemente dieselbe Anzahl von Wiederholungen wiederholen, wenn keine angezeigt wird.

int findCandidate(int a[], int size)
{
int count,temp=0,i,j, maj;

for (i = 0; i < size; i++) {
count=0;      
for(j=i;j<size;j++)
{
    if(a[j]==a[i])
    count++;
}
if(count>temp)
{   
    temp=count;
    maj=i;
}
else if(count==temp)
{   
    maj=-1; 
}
}


return maj;
}
0
Shivam Dawar
public class MajorityElement
    {
       public static void main(String[] args) 
          {
             int arr[]={3,4,3,5,3,90,3,3};

              for(int i=0;i<arr.length;i++)
                {
                  int count=0;
                   int j=0;

                    while(j<arr.length-1)
                     { 
                        if(i==j)
                        j=j+1;
                          if(arr[i]==arr[j])
                            count++;
                          j++;
                                  }

                             if(count>=arr.length/2)
                               {
                              System.out.println("majority element"+arr[i]);
                                   break;
    }
    }


}

}

0
rishabh singh

So mache ich es in C++ mit Vector und Multimap (JSON mit Wiederholungstasten).

#include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <iterator>

using namespace std;

vector <int> majorityTwoElement(vector <int> nums) {
  // declare variables
  multimap <int, int> nums_map;
  vector <int> ret_vec, nums_unique (nums);
  int count = 0;
  bool debug = false;

  try {
    // get vector of unique numbers and sort them
    sort(nums_unique.begin(), nums_unique.end());
    nums_unique.erase(unique(nums_unique.begin(), nums_unique.end()), nums_unique.end());

    // create map of numbers and their count
    for(size_t i = 0; i < nums_unique.size(); i++){
      // get number
      int num = nums_unique.at(i);
      if (debug) {
        cout << "num = " << num << endl;
      }

      // get count of number
      count = 0;  // reset count
      for(size_t j = 0; j < nums.size(); j++) {
        if (num == nums.at(j)) {
          count++;
        }
      }

      // insert number and their count into map (sorted in ascending order by default)
      if (debug) {
        cout << "num = " << num << "; count = " << count << endl;
      }
      nums_map.insert(pair<int, int> (count, num));
    }

    // print map
    if (debug) {
      for (const auto &p : nums_map) {
          cout << "nums_map[" << p.first << "] = " << p.second << endl;
      }
    }

    // create return vector
    if (!nums_map.empty()) {
      // get data
      auto it = prev(nums_map.end(), 1);
      auto it1 = prev(nums_map.end(), 2);
      int last_key = it->first;
      int second_last_key = it1->first;

      // handle data
      if (last_key == second_last_key) {  // tie for repeat count
        ret_vec.Push_back(it->second);
        ret_vec.Push_back(it1->second);
      } else {  // no tie
        ret_vec.Push_back(it->second);
      }
    }    
  } catch(const std::exception& e) {
    cerr << "e.what() = " << e.what() << endl;
    throw -1;
  }

  return ret_vec;
}

int main() {
  vector <int> nums = {2, 1, 2, 3, 4, 2, 1, 2, 2};

  try {
    // get vector
    vector <int> result = majorityTwoElement(nums);

    // print vector
    for(size_t i = 0; i < result.size(); i++) {
      cout << "result.at(" << i << ") = " << result.at(i) << endl;
    }
  } catch(int error) {
    cerr << "error = " << error << endl;
    return -1;
  }

  return 0;
}

// g++ test.cpp
// ./a.out
0
xinthose

Danke für die vorherigen Antworten, die mich dazu inspiriert haben, Bob Boyers Algo zu kennen. :)

Java-generische Version: Eine modifizierte Version des Boyer-Algorithmus

Hinweis: Ein Array mit primitivem Typ kann Wrapper verwenden.

import com.Sun.deploy.util.ArrayUtil;
import com.Sun.tools.javac.util.ArrayUtils;

/**
 * Created by yesimroy on 11/6/16.
 */
public class FindTheMajority {

/**
 *
 * @param array
 * @return the value of the majority elements
 */
public static <E> E findTheMajority(E[] array){
    E majority =null;
    int count =0;

    for(int i=0; i<array.length; i++){
        if(count==0){
            majority = array[i];
        }
        if(array[i].equals(majority)){
            count++;
        }else{
            count--;
        }

    }

    count = 0;
    for(int i=0; i<array.length ; i++){
        if(array[i].equals(majority)){
            count++;
        }
    }

    if(count > (array.length /2)){
        return majority;
    }else{
        return null;
    }
}

public static void main(String[] args){
    String[] test_case1 = {"Roy","Roy","Roy","Ane","Dan","Dan","Ane","Ane","Ane","Ane","Ane"};
    Integer[] test_case2 = {1,3,2,3,3,3,3,4,5};

    System.out.println("test_case1_result:" + findTheMajority(test_case1));
    System.out.println("test case1 the number of majority element should greater than" + test_case1.length/2);
    System.out.println();

    System.out.println("test_case2_result:" + findTheMajority(test_case2));
    System.out.println("test case2 the number of majority element should greater than" + test_case2.length/2);
    System.out.println();
}

}

0
Roy Guanyu

Wenn Sie eine Hash-Tabelle erstellen dürfen und davon ausgehen, dass die Suche nach Hash-Einträgen konstant ist, müssen Sie einfach hash_map jedem Eintrag die Anzahl der Vorkommen zuordnen.

Sie könnten einen zweiten Durchlauf durch die Tabelle durchführen, Sie erhalten denjenigen mit der höchsten Zählung, aber wenn Sie die Anzahl der Elemente in der Tabelle im Voraus kennen, werden Sie sofort wissen, ob wir beim ersten Durchlauf ein Mehrheitselement haben Erforderliche Anzahl für das Element.

Sie können natürlich nicht garantieren, dass es sogar eine Folge von zwei aufeinanderfolgenden Vorkommen des Elements gibt, z. B. hat 101010101010101010101 keine aufeinanderfolgenden 1en, es handelt sich jedoch um ein Majoritätselement.

Uns wird nichts darüber gesagt, ob es irgendeine Art von Anordnung auf dem Elementtyp gibt, obwohl wir offensichtlich zwei für Gleichheit vergleichen können müssen.

0
CashCow
    int majorityElement(int[] num) {
       int major=num[0], count = 1;
       for(int i=1; i<num.length;i++){
           if(count==0){
               count++;
               major=num[i];
           }
           else if(major==num[i]){
                    count++;
           }
           else 
               count--;
   }            
    return major;
}

Zeitkomplexität O(n)

0
Rajnish