【问题标题】:Write a mode method in Java to find the most frequently occurring element in an array用Java写一个mode方法来查找数组中出现频率最高的元素
【发布时间】:2013-03-21 11:03:15
【问题描述】:

问题是:

编写一个名为 mode 的方法,该方法返回整数数组中出现频率最高的元素。假设数组至少有一个元素,并且数组中的每个元素的值都在 0 到 100 之间。通过选择较低的值来打破平局。

例如,如果传递的数组包含值 {27, 15, 15, 11, 27},您的方法应该返回 15。(提示:您可能希望查看本章前面的 Tally 程序以获得关于如何解决这个问题的想法。)

下面是我的代码,除了单元素数组之外几乎可以工作

public static int mode(int[] n)
{
    Arrays.sort(n);
    
    int count2 = 0;
    int count1 = 0;
    int pupular1 =0;
    int popular2 =0;
    
    
    for (int i = 0; i < n.length; i++)
    {
            pupular1 = n[i];
            count1 = 0;    //see edit
        
        for (int j = i + 1; j < n.length; j++)
        {
            if (pupular1 == n[j]) count1++;
        }
        
        if (count1 > count2)
        {
                popular2 = pupular1;
                count2 = count1;
        }
        
        else if(count1 == count2)
        {
            popular2 = Math.min(popular2, pupular1);
        }
    }
    
    return popular2;
}

编辑:终于弄明白了。将 count1 = 0; 更改为 count1 = 1; 现在一切正常!

【问题讨论】:

  • +1 表示在提出问题之前做得很好(几乎可以工作,除了单元素数组)。您能否将您的解决方案发布为答案并将答案标记为正确?这样其他人就不会来帮助你的问题,认为它还没有得到回答。谢谢。
  • 我回应@Simon 的评论并补充说当前接受的答案(Gubatron 的)是错误的和不正确的。例如,它将在示例输入 {27, 15, 15, 11, 27} 上失败。 counts 的长度将为 5,counts[n[I]]++ 行将失败,因为它将尝试增加索引 27 处的元素,这超出了注释中的 shridhad 注释的范围。
  • 我同意西蒙的观点,您会将编辑中的解决方案移至下面的答案吗?我们喜欢在这里使用问答形式。
  • 将近 5 年后回顾这个问题,我很惊讶自己已经走了多远。那是我转行计算机科学的开始,我对mapset等数据结构一无所知。几乎是蛮力的方法让我在学习和工作中探索了高效的算法。它改变了我的生活:)

标签: java arrays methods mode


【解决方案1】:

您应该能够在 N 次操作中做到这一点,这意味着只需一次通过,O(n) 时间。

使用 map 或 int[](如果问题仅针对 int)来增加计数器,并使用一个变量来保存具有最大计数的键。每次增加计数器时,询问值是什么并将其与您上次使用的键进行比较,如果值更大,请更新键。

public class Mode {
public static int mode(final int[] n) {
    int maxKey = 0;
    int maxCounts = 0;

    int[] counts = new int[n.length];

    for (int i=0; i < n.length; i++) {
        counts[n[i]]++;
        if (maxCounts < counts[n[i]]) {
            maxCounts = counts[n[i]];
            maxKey = n[i];
        }
    }
    return maxKey;
}

public static void main(String[] args) {
    int[] n = new int[] { 3,7,4,1,3,8,9,3,7,1 };
    System.out.println(mode(n));
}
}

【讨论】:

  • 对不起,“counts[n[i]]++;”是什么意思做吗?
  • 如果int[] n= new int[] {12, 13, 13}; 它将通过ArrayIndexOutOfBoundsException。所以这个解决方案只有在你的数组中的每个数字都小于数组的长度时才有效。
  • 请注意,这不是数组可能包含 1-100 个整数的问题的正确实现,因为 counts[n[i]] 会溢出。此外,这仅在整数周围有边界的情况下才有用。
  • @shridhad 除了您提供的示例之外,此解决方案也将在问题中给出的示例上失败,即{27, 15, 15, 11, 27}
  • 如果数组中的给定值大于数组长度,则会抛出ArrayOutOfBounds异常。
【解决方案2】:

检查这个.. 简介:选择数组的每个元素,并将其与数组的所有元素进行比较,判断它是否等于被选中。

  int popularity1 = 0;
  int popularity2 = 0;
  int popularity_item, array_item; //Array contains integer value. Make it String if array contains string value.
  for(int i =0;i<array.length;i++){
      array_item = array[i];
      for(int j =0;j<array.length;j++){
          if(array_item == array[j])
             popularity1 ++;
          {
      if(popularity1 >= popularity2){
          popularity_item = array_item;
          popularity2 = popularity1;
      }
      popularity1 = 0;
  }
  //"popularity_item" contains the most repeted item in an array.

【讨论】:

  • 尝试在一个包含 1000 个随机数的数组上运行它。多久时间?一个包含 1,000,000 个随机数的数组怎么样?
【解决方案3】:

我会使用此代码。它包括一个instancesOf 函数,它贯穿每个数字。

public class MathFunctions {

public static int mode(final int[] n) {
    int maxKey = 0;
    int maxCounts = 0;

    for (int i : n) {
        if (instancesOf(i, n) > maxCounts) {
            maxCounts = instancesOf(i, n);
            maxKey = i;
        }
    }

    return maxKey;
}

public static int instancesOf(int n, int[] Array) {
    int occurences = 0;
    for (int j : Array) {
        occurences += j == n ? 1 : 0;
    }
    return occurences;
}

public static void main (String[] args) {
    //TODO Auto-generated method stub
    System.out.println(mode(new int[] {100,200,2,300,300,300,500}));
}
}

我注意到 Gubatron 发布的代码在我的计算机上不起作用;它给了我一个ArrayIndexOutOfBoundsException

【讨论】:

  • 在包含 1,000,000 个元素的数组上运行速度有多快?
  • @phoog,真的很慢。
  • @Cornul11 如果我没记错的话,我问的是一个反问。
【解决方案4】:

此代码计算众数、中位数和均值。它经过测试并且确实有效。它是一个从头到尾的完整程序,可以编译。

import java.util.Arrays;
import java.util.Random;
import java.math.*;
/**
 *
 * @author Mason
 */
public class MODE{

    public static void main(String args[])
    {
        System.out.print("Enter the quantity of random numbers  ===>>  ");
        int listSize = Expo.enterInt();
        System.out.println();
        ArrayStats intStats = new ArrayStats(listSize);
        intStats.randomize();
        intStats.computeMean();
        intStats.computeMedian();
        intStats.computeMode();
        intStats.displayStats();
        System.out.println();
    }
}


class ArrayStats
{

    private int list[];
    private int size;
    private double mean;        
    private double median;      
    private int mode;           

    public ArrayStats(int s)//initializes class object
    {
        size = s;
        list = new int[size];
    }

    public void randomize()
    {
        //This will provide same numbers every time... If you want to randomize this, you can
        Random rand = new Random(555);
        for (int k = 0; k < size; k++)
            list[k] = rand.nextInt(11) + 10;  
    }

    public void computeMean()
    {
               double accumulator=0;
               for (int index=0;index<size;index++)
               accumulator+= list[index];

               mean = accumulator/size;
    }

        public void computeMedian()
{
        Arrays.sort(list);
                if((size%2!=0))
                    median = list[((size-1)/2)];
                else if(size!=1&&size%2==0)
                {
                    double a =(size)/2-0.5;
                    int a2 =  (int)Math.ceil(a);
                    double b =(size)/2-0.5;
                    int b2 = (int)Math.floor(b);
                    median = (double)(list[a2]+list[b2])/2;
                }
                else if (size ==1)
                    median = list[0];
        }

    public void computeMode()
    {
 int popularity1 = 0;
  int popularity2 = 0;
  int array_item; //Array contains integer value. Make it String if array contains string value.
  for(int i =0;i<list.length;i++){
      array_item = list[i];
      for(int j =0;j<list.length;j++){
          if(array_item == list[j])
             popularity1 ++;
      }
      if(popularity1 >= popularity2){
          mode = array_item;
          popularity2 = popularity1;
      }


      popularity1 = 0;
  }}

    public void displayStats()
    {
        System.out.println(Arrays.toString(list));
        System.out.println();
        System.out.println("Mean: " + mean);
        System.out.println("Median: " + median);
        System.out.println("Mode: " + mode);
        System.out.println();
    }

}

【讨论】:

  • 我没有投反对票,但你的模式算法效率很低。你试过输入1000000吗?
  • 不,我没有……至少我的挖掘足够简单,让普通的低级程序员能够理解和实现……
【解决方案5】:

对于此类问题,您应该使用 hashmap。将每个元素输入 hashmap 需要 O(n) 时间,检索元素需要 o(1) 时间。在给定的代码中,我基本上取了一个全局最大值并将其与从 hashmap 的“get”中接收到的值进行比较,每次我在其中输入一个元素时,看看:

hashmap有两部分,一是key,二是value,当你对key做get操作时,返回它的值。

public static int mode(int []array)
{
    HashMap<Integer,Integer> hm = new HashMap<Integer,Integer>();
    int max  = 1;
    int temp = 0;

    for(int i = 0; i < array.length; i++) {

        if (hm.get(array[i]) != null) {

            int count = hm.get(array[i]);
            count++;
            hm.put(array[i], count);

            if(count > max) {
                max  = count;
                temp = array[i];
            }
        }

        else 
            hm.put(array[i],1);
    }
    return temp;
}

【讨论】:

  • 如果所有元素都是唯一的怎么办。你确定我们会找到结果吗?
  • 如果所有元素都是唯一的,则没有频繁出现的元素:)
  • 如果所有元素都是唯一的,则所有项目的频率为 1 并且是模式的候选者。根据问题,最低元素将是模式。
【解决方案6】:

这是我的答案。

public static int mode(int[] arr) {
    int max = 0;
    int maxFreq = 0;

    Arrays.sort(arr);
    max = arr[arr.length-1];

    int[] count = new int[max + 1];

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

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

    for (int i = 0; i < count.length; i++) {
        if (count[i] == maxFreq) {
            return i;
        }
    }
    return -1;
}

【讨论】:

  • 如果数组arr 中的数据包含负值,这将失败。如果数组包含非常大的值,例如 2,147,483,647,您也可能会遇到问题。
【解决方案7】:
public int mode(int[] array) {
    int mode = array[0];
    int maxCount = 0;
    for (int i = 0; i < array.length; i++) {
        int value = array[i];
        int count = 1;
        for (int j = 0; j < array.length; j++) {
            if (array[j] == value) count++;
            if (count > maxCount) {
                mode = value;
                maxCount = count;
            }
        }
    }
    return mode;
}

【讨论】:

    【解决方案8】:

    我知道这个问题是不久前提出的,但我想添加一个我认为可以扩展原始问题的答案。这个问题的附录是在不依赖预设范围(在本例中为 0 到 100)的情况下编写模式方法。我已经为 mode 编写了一个版本,它使用原始数组中的值范围来生成计数数组。

    public static int mode(int[] list) {
    
        //Initialize max and min value variable as first value of list
        int maxValue = list[0]; 
        int minValue = list[0];
    
        //Finds maximum and minimum values in list
        for (int i = 1; i < list.length; i++) {
            if (list[i] > maxValue) {
                maxValue = list[i];
            }
    
            if (list[i] < minValue) {
                minValue = list[i];
            }
        }
    
        //Initialize count array with (maxValue - minValue + 1) elements  
        int[] count = new int[maxValue - minValue + 1];
    
        //Tally counts of values from list, store in array count
        for (int i = 0; i < list.length; i++) {
            count[list[i] - minValue]++; //Increment counter index for current value of list[i] - minValue
        }
    
        //Find max value in count array
        int max = count[0]; //Initialize max variable as first value of count
    
        for (int i = 1; i < count.length; i++) {
            if (count[i] > max) {
                max = count[i];
            }
        }
    
        //Find first instance where max occurs in count array
        for (int i = 0; i < count.length; i++) {
            if (count[i] == max) {
                return i + minValue; //Returns index of count adjusted for min/max list values - this is the mode value in list
            }
        }
        return -1; //Only here to force compilation, never actually used
    }
    

    【讨论】:

      【解决方案9】:

      我最近做了一个程序,可以计算一些不同的统计数据,包括模式。虽然编码可能是初级的,但它适用于任何整数数组,并且可以修改为双精度、浮点数等。对数组的修改是基于删除数组中不是最终模式值的索引.这允许您显示所有模式(如果有多个)以及出现的数量(模式数组中的最后一项)。下面的代码就是运行这段代码所需要的getMode方法以及deleteValueIndex方法

      import java.io.File;
      import java.util.Scanner;
      import java.io.PrintStream;
      
      public static int[] getMode(final int[] array) {           
        int[] numOfVals = new int[array.length];
        int[] valsList = new int[array.length];
      
        //initialize the numOfVals and valsList
      
        for(int ix = 0; ix < array.length; ix++) {
           valsList[ix] = array[ix];
        }
      
        for(int ix = 0; ix < numOfVals.length; ix++) {
           numOfVals[ix] = 1;
        }
      
        //freq table of items in valsList
      
        for(int ix = 0; ix < valsList.length - 1; ix++) {
           for(int ix2 = ix + 1; ix2 < valsList.length; ix2++) {
              if(valsList[ix2] == valsList[ix]) {
                 numOfVals[ix] += 1;
              }
           }
        }
      
        //deletes index from valsList and numOfVals if a duplicate is found in valsList
      
        for(int ix = 0; ix < valsList.length - 1; ix++) {   
           for(int ix2 = ix + 1; ix2 < valsList.length; ix2++) {
              if(valsList[ix2] == valsList[ix]) {
                 valsList = deleteValIndex(valsList, ix2);
                 numOfVals = deleteValIndex(numOfVals, ix2);
              }
           }
        }
      
        //finds the highest occurence in numOfVals and sets it to most
      
        int most = 0;
      
        for(int ix = 0; ix < valsList.length; ix++) {
           if(numOfVals[ix] > most) {
              most = numOfVals[ix];
           }
        }
      
        //deletes index from valsList and numOfVals if corresponding index in numOfVals is less than most
      
        for(int ix = 0; ix < numOfVals.length; ix++) {
           if(numOfVals[ix] < most) {
              valsList = deleteValIndex(valsList, ix);
              numOfVals = deleteValIndex(numOfVals, ix);
              ix--;
           }
        }
      
        //sets modes equal to valsList, with the last index being most(the highest occurence)
      
        int[] modes = new int[valsList.length + 1];
      
        for(int ix = 0; ix < valsList.length; ix++) {
           modes[ix] = valsList[ix];
        }
      
        modes[modes.length - 1] = most;
      
        return modes;
      
      }
      
      public static int[] deleteValIndex(int[] array, final int index) {   
        int[] temp = new int[array.length - 1];
        int tempix = 0;
      
        //checks if index is in array
      
        if(index >= array.length) {
           System.out.println("I'm sorry, there are not that many items in this list.");
           return array;
        }
      
        //deletes index if in array
      
        for(int ix = 0; ix < array.length; ix++) {
           if(ix != index) {
              temp[tempix] = array[ix];
              tempix++;
           }
        }
        return temp;
      }
      

      【讨论】:

        【解决方案10】:

        根据@codemania23 和Java Docs for HashMap 的回答,我编写了这段代码,并测试了一个返回数组中出现次数最多的数字 的方法。

        import java.util.HashMap;
        
        public class Example {
        
            public int mostOcurrentNumber(int[] array) {
                HashMap<Integer, Integer> map = new HashMap<>();
                int result = -1, max = 1;
                for (int arrayItem : array) {
                    if (map.putIfAbsent(arrayItem, 1) != null) {
                        int count = map.get(arrayItem) + 1;
                        map.put(arrayItem, count);
                        if (count > max) {
                            max = count;
                            result = arrayItem;
                        }
                    }
                }
        
                return result;
            }
        }
        

        单元测试

        import org.junit.Test;
        
        import static junit.framework.Assert.assertEquals;
        
        public class ExampleTest extends Example {
        
            @Test
            public void returnMinusOneWhenInputArrayIsEmpty() throws Exception {
                int[] array = new int[0];
                assertEquals(mostOcurrentNumber(array), -1);
            }
        
            @Test
            public void returnMinusOneWhenElementsUnique() {
                int[] array = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
                assertEquals(-1, mostOcurrentNumber(array));
            }
        
            @Test
            public void returnOne() throws Exception {
                int[] array = new int[]{0, 1, 0, 0, 1, 1, 1};
                assertEquals(1, mostOcurrentNumber(array));
            }
        
            @Test
            public void returnFirstMostOcurrentNumber() throws Exception {
                int[] array = new int[]{0, 1, 0, 1, 0, 0, 1, 1};
                assertEquals(0, mostOcurrentNumber(array));
            }
        }
        

        【讨论】:

          【解决方案11】:

          这不是最快速的方法,但如果您不想让自己参与 HashMaps 并且还想避免使用 2 个 for 循环来解决复杂性问题,这很容易理解......

              int mode(int n, int[] ar) {
              int personalMax=1,totalMax=0,maxNum=0;
          
              for(int i=0;i<n-1;i++)
              {
          
                  if(ar[i]==ar[i+1])
                  {
                      personalMax++;
          
                      if(totalMax<personalMax)
                      {
                          totalMax=personalMax;
                          maxNum=ar[i];
                      }
                  }    
                  else
                  {
                      personalMax=1;
                  }
              }
              return maxNum;
          }
          

          【讨论】:

            【解决方案12】:

            在这里,我使用单循环进行编码。我们从 a[j-1] 获取模式,因为 localCount 最近在 j 为 j-1 时更新。 N 也是数组的大小,计数被初始化为 0。

                    //After sorting the array 
                    i = 0,j=0;
                    while(i!=N && j!=N){
                        if(ar[i] == ar[j]){
                            localCount++;
                            j++;
                        }
                        else{
                            i++;
                            localCount = 0;
                        }
                        if(localCount > globalCount){
                            globalCount = localCount;
                            mode = ar[j-1]; 
                        }
                    }
            

            【讨论】:

              【解决方案13】:
                  Arrays.sort(arr);
                  int max=0,mode=0,count=0;
                  for(int i=0;i<N;i=i+count) {
                      count = 1;
                      for(int j=i+1; j<N; j++) {
                          if(arr[i] == arr[j])
                              count++;
                      }
                      if(count>max) {
                          max=count;
                          mode = arr[i];
                      }
                  }
              

              【讨论】:

                【解决方案14】:

                导入 java.util.HashMap;

                公共类 SmallestHighestRepeatedNumber { 静态 int arr[] = { 9, 4, 5, 9, 2, 9, 1, 2, 8, 1, 1, 7, 7 };

                public static void main(String[] args) {
                    int mode = mode(arr);
                    System.out.println(mode);
                }
                
                public static int mode(int[] array) {
                    HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
                    int max = 1;
                    int temp = 0;
                
                    for (int i = 0; i < array.length; i++) {
                
                        if (hm.get(array[i]) != null) {
                
                            int count = hm.get(array[i]);
                            count++;
                            hm.put(array[i], count);
                
                            if (count > max || temp > array[i] && count == max) {
                                temp = array[i];
                                max = count;
                            }
                        } else
                            hm.put(array[i], 1);
                    }
                    return temp;
                }
                

                }

                【讨论】:

                • 你能提供一些上下文吗?
                • 你只是复制粘贴了我的答案,伙计
                猜你喜欢
                • 1970-01-01
                • 2019-08-15
                • 1970-01-01
                • 2017-07-08
                • 2012-11-03
                • 2018-04-04
                • 2017-07-18
                • 2011-09-09
                • 1970-01-01
                相关资源
                最近更新 更多