2012-02-22 3 views
-1

Кто-нибудь знает, как найти режимы в массиве, когда есть более одного режима? У меня есть этот код, который находит один режим. Но я имею дело с массивом, который имеет более одного режима, мультимодальный массив, и я должен печатать каждый режим ровно один раз. Вот мой код, может кто-нибудь мне помочь? Благодарю.Поиск режимов a a array

public static int mode(int a[]) 
{ 
    int maxValue=0, maxCount=0; 

    for (int i = 0; i < a.length; ++i) 
    { 
     int count = 0; 
     for (int j = 0; j < a.length; ++j) 
     { 
      if (a[j] == a[i]) ++count; 
     } 

     if (count > maxCount) 
     { 
      maxCount = count; 
      maxValue = a[i]; 
     } 
    } 

    return maxCount; 
} 

public static Integer[] modes(int a[]) 
{ 
    List<Integer> modes = new ArrayList<Integer>(); 
    int maxCount=0; 
    for (int i = 0; i < a.length; ++i) 
    { 
     int count = 0; 
     for(int j = 0; j < a.length; ++j) 
     { 
      if (a[j] == a[i]) ++count; 
     } 

     if (count > maxCount) 
     { 
      maxCount = count; 
      modes.clear(); 
      modes.add(a[i]); 
     } 
     else if (count == maxCount) 
     { 
      modes.add(a[i]); 
     } 
    } 
    return modes.toArray(new Integer[modes.size()]); 
} 
+0

Это домашнее задание? –

+0

не очень, я программирую на веб-сайте в Интернете, и это одна из проблем. –

+0

@ DanielFarmer Элементы вашего целочисленного массива имеют определенный диапазон значений, например arr [k] составляет от 1 до 100, или он может хранить любое целочисленное значение? –

ответ

3

Поскольку ваши элементы будут от 10 до 1000, вы можете использовать массив Counter. В этом массиве счетчиков вы можете хранить отсчеты значения элемента a [i]. Я думаю, вы можете понять это лучше в коде:

public static List<Integer> mode(int[] a) { 
    List<Integer> lstMode = new ArrayList<Integer>(); 
    final int MAX_RANGE = 1001; 
    int[] counterArray = new int[MAX_RANGE]; //can be improved with some maths :)! 
    //setting the counts for the counter array. 
    for (int x : a) { 
     counterArray[x]++; 
    } 
    //finding the max value (mode). 
    int maxCount = counterArray[0]; 
    for(int i = 0; i < MAX_RANGE; i++) { 
     if (maxCount < counterArray[i]) { 
      maxCount = counterArray[i]; 
     } 
    } 
    //getting all the max values 
    for(int i = 0; i < MAX_RANGE; i++) { 
     if (maxCount == counterArray[i]) { 
      lstMode.add(new Integer(i)); 
     } 
    } 
    return lstMode; 
} 

Если вход будет иметь элементы за пределами 1000, вы можете посмотреть на карте ответа (как и в других постах).

1

Один подход заключается в запуске (примерно) текущий код дважды: в первый раз, найти maxCount, и второй раз, распечатать каждое значение, которое происходит maxCount раз. (Вам необходимо внести некоторые изменения для того, чтобы напечатать каждый режим только один раз, вместо того, чтобы напечатать его maxCount раз.)

+0

это именно моя проблема ... Я уже получил его для печати maxCount раз, но я понятия не имею, как распечатать его ровно один раз. –

+0

@ DanielFarmer: Опубликуйте свой текущий код - код, который печатает его 'maxCount' раз - и я дам вам еще один намек. :-) – ruakh

+0

уверен, я редактировал мой вопрос.возвращает Integer [], который печатает режимы maxCount раз. –

1

Вместо того, чтобы один maxValue занесите моды в ArrayList<Integer>.

if (count == maxCount) 
{ 
    modes.add(a[i]); 
} 
else if (count > maxCount) 
{ 
    modes.clear(); // discard all the old modes 
    modes.add(a[i]); 
    maxCount = count; 
} 

и начать с j = i вместо j = 0.

+0

Я пробовал это .. но он не будет печатать режимы только один раз :( –

+1

@ DanielFarmer Вы правы - извините, я исправил ошибку. – tom

2

Мы должны сделать это легкий путь и использовать структуру Map данных в следующем формате:

Map<Integer,Integer> 

А затем сохранить текущую сумму, после чего вы перебрать набор ключей и вытаскивать наибольшее значение (s) с карты.

Если вы хотите оставаться с реализацией List вы можете сделать следующее, чтобы удалить простофили:

Set s = new HashSet(list); 
list = new ArrayList(s); 
+0

Ваша реализация безвозмездно проходит через входной массив n^2 раза для входного массива размера n. Подход Woot намного быстрее. – paislee

+0

Я считаю, что это 2n обхода. 1 для проверки вставки, 1 для набора ключей – Woot4Moo

+0

Извините за путаницу. означает OP. Я сделаю это как комментарий вопроса. +1 – paislee

0

Поскольку ваши значения массива только в диапазон от [10,1000], вы можете использовать Map<Integer,Integer> для хранения отображения между каждым обнаружено значение массива (ключ карты) и его счет (значение карты). A HashMap здесь будет работать очень хорошо.

Чтобы увеличить счетчик:

int count = (map.contains(a[i]) ? map.get(a[i]) : 1; 
map.put(a[i],count); 

Continue отслеживать максимальное кол, как вы уже делаете, и в конце концов, просто перебрать карты и собрать все ключи карты со значением карты, равным максимальному сосчитать.