【问题标题】:Finding the Mode of Integers in an Array查找数组中整数的众数
【发布时间】:2014-07-19 17:30:33
【问题描述】:

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

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

我在查看特定输入的问题时遇到了问题。例如:

mode({27, 15, 15, 27, 11, 11, 11, 14, 15, 15, 16, 19, 99, 100, 0, 27}) 返回 15 是正确的,但是 mode({1 , 1, 2, 3, 3}) 在应该为 1 时返回 3。

代码如下:

public static int mode(int[] input) {
    int returnVal = input[0]; // stores element to be returned
    int repeatCount = 0; // counts the record number of repeats
    int prevRepCnt = 0; // temporary count for repeats

    for (int i=0; i<input.length; i++) { // goes through each elem

        for (int j=i; j<input.length; j++) { // compares to each elem after the first elem

            if (i != j && input[i] == input[j]) { // if matching values
                repeatCount++; // gets the repeat count

                if (repeatCount>=prevRepCnt) { // a higher count of repeats than before
                    returnVal=input[i]; // return that element
                }
                prevRepCnt = repeatCount; // Keeps the highest repeat record
            }
            repeatCount=0; // resets repeat Count for next comparison
        }
    }
    return returnVal;
}

【问题讨论】:

    标签: java arrays mode


    【解决方案1】:

    我的方法是使用 HashMaps。

    它将通过返回最小值来处理多模态数组。

     public static int getModeOf(int[] elements){
    
            HashMap<Integer, Integer> frequencyOfElements = new HashMap<Integer, Integer>();
    
            for(int i=0;i<elements.length;i++){
                // Put the key into the map if it's not present.
                // If it is present, update frequency.
                if(!frequencyOfElements.containsKey(elements[i])){
                    frequencyOfElements.put(elements[i],1);
                }
                else{
                    frequencyOfElements.put(elements[i],frequencyOfElements.get(elements[i])+1);
                }
            }
    
            ArrayList<Integer> modes = new ArrayList<Integer>();
            int frequencyOfCurrentMode = 0;
    
            // We assume the first entry is the mode, then compare the remaining elements
            // from there......
            for(Map.Entry<Integer, Integer> entry : frequencyOfElements.entrySet() ){
                if(entry.getValue() >= frequencyOfCurrentMode){
                   modes.add(entry.getKey());
                   frequencyOfCurrentMode = entry.getValue();
               }
            }
    
            // If we've more than one mode, place the lowest first......
            if(modes.size() > 1) Collections.sort(modes);
    
            return modes.get(0);
        }
    

    【讨论】:

      【解决方案2】:

      根据您的代码,您需要更改的只是。

      public static int mode(int[] input) {
          int returnVal = input[0]; // stores element to be returned
          int repeatCount = 0; // counts the record number of repeats
          int prevRepCnt = 0; // temporary count for repeats
      
      for (int i=0; i<input.length; i++) { // goes through each elem
      
          for (int j=i; j<input.length; j++) { // compares to each elem after the first elem
      
              if (i != j && input[i] == input[j]) { // if matching values
                  repeatCount++; // gets the repeat count
      
                  if (repeatCount>=prevRepCnt) { // a higher count of repeats than before
                      returnVal=input[i]; // return that element
                  }
                  prevRepCnt = repeatCount; // Keeps the highest repeat record
              }
              repeatCount=0; // resets repeat Count for next comparison
          }
      }
      return returnVal;
      }
      

      这是您需要更改的内容。

      if (repeatCount>prevRepCnt) { // a higher count of repeats than before
      
      • 去掉等号应该没问题。

      【讨论】:

        【解决方案3】:

        我最近分析了四种计算数组众数的方法:

        • 如果数组中的数字范围很小,则使用计数排序 - O(N) 时间,(N) 空间,但非常有效。此解决方案直接适用于您所询问的问题,因为数组中只有 101 个可能的值。
        • 哈希表中数组中的索引元素 - O(N) 时间,O(N) 空间。如果取自较大范围的值(例如所有整数),则此解决方案适用。
        • 对数组进行排序,然后计算连续相等的元素 - O(NlogN) 时间,O(1) 空间。如果数组太大而无法构建索引,则此解决方案适用。
        • 对数组进行部分排序,但跳过小于当前候选者的分区 - O(NlogN) 时间,O(1) 空间,但比对数组完全排序更有效,因为将跳过许多分区。

        您可以在本文中找到所有四种方法和性能比较的源代码(尽管是 C#):Finding Mode of an Array

        【讨论】:

          【解决方案4】:

          我会声明另一个变量来跟踪“较低的值”。并检查 input[i] 值是否小于 lowerValue 变量,当它具有相同的计数时。请注意,我根据您的情况将 > & = 分开。

          int 低值;

          public static int mode(int[] input) {
              int returnVal = input[0]; // stores element to be returned
              int repeatCount = 0; // counts the record number of repeats
              int prevRepCnt = 0; // temporary count for repeats
              int lowerValue = Integer.MAX_VALUE; // initalize it with the highest integer value - 2147483647
          
              for (int i=0; i<input.length; i++) { // goes through each elem
          
                  for (int j=i; j<input.length; j++) { // compares to each elem after the first elem
          
                      if (i != j && input[i] == input[j]) { // if matching values
                          repeatCount++; // gets the repeat count
          
                          if (repeatCount>prevRepCnt) { // a higher count of repeats than before
                              returnVal=input[i]; // return that element
                              lowerValue = returnVal; // set the variable lowerValue to be the lower value
                          }
                          else if (repeatCount == prevRepCnt) && (input[i] < lowerValue) { // if it's the same number of count, take in whichever number is lower
                              returnVal=input[i]; // return that element
                              lowerValue = returnVal; // set the variable lowerValue to be the lower value
                          }
                          prevRepCnt = repeatCount; // Keeps the highest repeat record
                      }
                      repeatCount=0; // resets repeat Count for next comparison
                  }
              }
              return returnVal;
          }
          

          【讨论】:

          • 你在 else if 之前缺少一个结束括号。
          【解决方案5】:

          这里有一个更简单的方法来解决这个问题。创建一个名为 count 大小为 101 的数组。索引 (0-100) 表示您正在计数的数字。遍历输入数组并计算每个数字的出现次数。最后,比较计数以找到出现次数最多的计数(并列到较小的数字):

          public static int mode(int[] input) {
          
              int[] count = new int[101];
          
              //count the occurrences
              for (int i=0; i < input.length; i++) {
                  count[input[i]]++;
              }
          
              //go backwards and find the count with the most occurrences
              int index = count.length-1;
              for (int i=count.length-2; i >=0; i--) {
                  if (count[i] >= count[index])
                      index = i;
              }
          
              return index;
          }
          

          【讨论】:

          • 这是一个非常简洁的解决方案,但它限制了您可以使用的值的范围。您可以使用变量而不是 101,但假设最大数字非常大,例如 347616。count 数组将无缘无故地占用大量内存。
          猜你喜欢
          • 2015-07-04
          • 2015-10-30
          • 2015-05-13
          • 1970-01-01
          • 2018-08-27
          • 2015-12-08
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多