【问题标题】:Finding Multiple Modes In An Array在数组中查找多种模式
【发布时间】:2023-03-09 13:54:02
【问题描述】:

我正在尝试编写一个 java 方法来查找数组中的所有模式。我知道有一种简单的方法可以在数组中找到模式,但是当有多个单一模式时,我的方法只输出其中一个。我试图找到一种方法,但不确定如何解决这个问题。谁能帮我找出数组中的所有模式?谢谢。

是的,这是我的代码,即使存在多种模式,它也只输出一种模式。

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 maxValue;
}

好的,这是一个例子: 30 30 30 34 34 23

在这组数字中只有一个众数,即 30。

30 30 30 34 34 34 23

但是在这个集合中有两种模式,30 和 34。我希望我的代码能够同时输出它们,而它只打印一个。它只打印 30 个。

【问题讨论】:

  • mode 是什么意思?在您所指的数组中查找模式的简单方法是什么。您的方法的任何代码只输出其中一个?
  • 是的,这是我的代码,它只输出一种模式,即使存在多个模式。公共静态 int 模式(int a[]){ int maxValue=0, maxCount=0; for (int i = 0; i maxCount) { maxCount = count;最大值 = a[i]; } } 返回最大值; }
  • @Daniel,不要将代码放在 cmets 中;只需编辑您的问题。
  • 是的,抱歉我修改了它。
  • @Robin - 这就是mode 的含义 - 数组中最常出现的项目(数学术语中的“集合”)。在 2 个项目出现相同次数的平局的情况下,数组为 bimodal,如果有超过 2 个项目出现相同次数,multimodal

标签: java mode


【解决方案1】:

以下代码将返回一个包含模式的Integer[]。如果您需要 int[],您仍然需要手动将 Integer 实例转换为 ints。可能不是最有效的版本,但它与您的代码非常匹配

public static Integer[] mode(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()] );
}

【讨论】:

  • 是的,你几乎被锁定在 O(n^2) 中。我能想到的唯一优化是如果您要使用maxCount 来限制内部循环;如果((j.length - (j + 1)) + count) &lt; maxCount 你可以保释。
【解决方案2】:

经过一夜的编程,我最终得到了一个程序,可以打印出数组的模式。或者甚至会告诉您是否没有模式(例如,如果没有输入多次发生或所有输入发生的次数相同:例如 1、1、2、2、3、3、4、4 )。该程序的一些限制是您必须输入多个数字,并且您不能输入超过 10000 个数字或负数(如果您想输入一个负数,您只需调整所有涉及值的 for 循环[][] 数组。关于我的程序的一些很酷的事情是它会打印出每个输入发生的次数以及数组的模式。并且所有打印输出的语法都会根据信息量而变化(例如。数组的模式是 2;数组的模式是 1 和 2;数组的模式是 0、2、5 和 8)。程序中还有一个冒泡排序函数示例,供任何认为他们在他们的模式程序中需要一个排序器功能。希望这会有所帮助,我包含了很多伪代码来帮助那些看不到我的逻辑在整个程序中如何进展的人。(仅供参考:它是 java,并在 BlueJ 中编译)

import java.util.Scanner;
public class Mode
{
    public static void main (String args [])
    {
        Scanner scan = new Scanner(System.in);
        int MAX_INPUTS = 10000; boolean flag = false;
        System.out.print ("Input the size of your array: ");
        int size; // How many nubers will be in the user array
        do
        {
            size = scan.nextInt();
            if (size == 1)
            {
                System.out.print ("\nError. You must enter a number more than 1.\n\n"); 
                continue;
            }
            else if (size > MAX_INPUTS || size < 0)
            {
                System.out.print ("\nError. You muste enter a number less than " + MAX_INPUTS + " or greater than 0\n\n");
                continue;
            }
            else
                flag = true; // a ligit answer has been entered.
        }
        while (flag != true);
        int array[] = new int[size], values[][] = new int[2][MAX_INPUTS + 1], ticks = 0;

        System.out.print ("\nNow input the numbers for your array.\n\n");

        /* Taking inputs from the user */        
        while (ticks < size)
        {
            System.out.print ("Number " + (ticks + 1) + ": ");
            array[ticks] = scan.nextInt();
            if (array[ticks] > MAX_INPUTS || array[ticks] < 0)
            {
                System.out.print ("\nError. Number cannot be greater than " + MAX_INPUTS + " or less than 0\n\n");
                continue;
            }               
            ++ticks;
        }

        /* 
         * values[][] array will hold the info for how many times numbers 0 - 10000 appear in array[]. Column 0 will hold numbers from 0 -1000, and column 1 will hold the number of
         * of repititions the number in column 0 occured in the users inputed array.
         */

        for (int i = 0; i < MAX_INPUTS; ++i) // Initalize Column zero with numbers starting at zeor, and ending and MAX_INPUTS.
            values[0][i] = i;

        for (int i = 0; i < size; ++i) // Find the repatitions of the numbers in array[] that correspond to the number in column zere of values[][].
            for (int j = 0; j < MAX_INPUTS; ++j)
                if (array[i] == j)
                    ++values[1][j];

        sort (array, size);
        System.out.print ("\n\nHere are the numbers you entered.\n\n"); // show the values the user entered in ascending order.

        for (int i = 0; i < size; ++i)
        {
            if (i == size - 1) // the last inputed number
                System.out.print (array[i]); // don't allow an extra comma.
            else
                System.out.print (array[i] + ", ");
        }

        // Show the user how many times each of the values he/she entered occured.

        System.out.print ("\n\nThis is the amount of times each of the values you entered occured:\n");

        for (int i = 0; i < MAX_INPUTS; ++i)
        {
            if (values[1][i] == 1)
                System.out.print (i + " was entered " + values[1][i] + " time\n"); // avoid: 2 was entered 1 times
            else if (values[1][i] != 0)
                System.out.print (i + " was entered " + values[1][i] + " times\n"); // avoid: 2 was entered 2 time
        }


        /* -------------------------------------------------------------------- | Finding the Mode/Modes | -------------------------------------------------------------------- */
        /* The process begins with creating a second array that is the exactly the same as the values[][] (First for loop). Then I sort the duplicate[] array to find the mode 
         * (highest number in the duplicate[]/values[][] arrays. Int max is then assigned the highest number. Remembering that the values[][] array: column 0 contains numbers ranging
         * from 1 to 10000, it keeps track of where the numbers in column were originally located, in which you can compare to the duplicate array which is sorted. Then I can set 
         * up a flag that tells you whether there is more than one mode. If so, the printing of these modes will look neater and the grammar can be changed accordingly.
         */

        int duplicate[] = new int [10001], mode[] = new int [size], max, mode_counter = 0;
        boolean multi_mode = false, all_same;

        for (int i = 0; i < MAX_INPUTS; ++i)
            duplicate[i] = values[1][i]; // copy values array.

        sort (duplicate, MAX_INPUTS);
        max = duplicate[MAX_INPUTS - 1]; // the last number in the sorted array is the greatest.
        all_same = test (duplicate, MAX_INPUTS, size, max); // this is the test to see if all the numbers in the user array occured the same amount of times.
        int c = 0; // a counter

        /* The mode of the user inputed array will be recorded in the values array. The sort of the duplicate array told me what was the higest number in that array. Now I can 
         * see where that highest number used to be in the original values array and recored the corresponding number in the column zero, which was only filled with numbers 0 -
         * 10000. Thus telling me the mode/modes.
         */

        for (int i = 0; i < MAX_INPUTS; ++i)
        {
            if (values[1][i] == max)
            {
                mode[c++] = values[0][i];
                ++mode_counter;
            }
        }

        if (mode[1] != 0) //mode[0] (the first cell, has a number stored from the last for loop. If the second cell has a number other than zero, that tells me there is more than 1 mode.
            multi_mode = true;

        if (multi_mode == false)
            System.out.print ("\nThe mode of your array is " + mode[0]); // For correct grammer.
        else if (all_same == true)
            System.out.print ("\nAll of the numbers entered appeared the same amount of times. "); // See the boolean function for more details
        else // If here there is more than one mode.
        {
            System.out.print ("\nThe modes of yoru array are ");
            for (int i = 0; i < mode_counter; ++i)
            {
                if (mode_counter > 2 && i == (mode_counter - 1))  // If there is more than two modes and the final mode is to be printed.
                    System.out.print ("& " + mode[i]);
                else if (mode_counter == 2)
                { // This is true if there is two modes. The else clause will print the first number, and this will print the amper sign and the second mode.
                    System.out.print (mode[0] + " & " + mode[1]); 
                    break;
                }
                else
                    System.out.print (mode[i] + ", ");
            }
        }
    }

    public static void sort (int list[], int max) // Its the bubble sort if you're wondering.
    {
        int place, count, temp;        
        for (place = 0; place < max; ++place)
            for (count = max - 1; count > place; --count)
                if (list[count - 1] > list[count])
                {
                        temp = list[count-1];
                        list[count - 1] = list[count];
                        list[count] = temp;
                }
    }

    /* The test to see if there isn't a mode. If the amount of the mode number is the same as the amount of numbers there are in the array is true, or if the size entered by the 
     * user (input) modulo the mode value is equal to zero (say, all the numbers in an array of ten were entered twice: 1, 1, 2, 2, 3, 3, 4, 4, 5, 5). */
    public static boolean test (int list[], int limit, int input, int max)
    {
        int counter = 0, anti_counter = 0;
        for (int i = 0; i < limit; ++i)
            if (list[i] == max)
                ++counter; // count the potential modes
            else if (list[i] !=0 && list[i] != max)
                ++anti_counter; // count every thing else except zeros.


        if (counter == input || (input % max == 0 && anti_counter == 0) )
            return true;
        else
            return false;
    }
}

【讨论】:

    【解决方案3】:

    尽管这可能不是最有效的解决方案,但它会打印所有最高模式:

    public static int mode(int a[]) {
        int maxValue=-1, 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];
            }
        }
    
        //loop again and print only the highest modes
        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) {
                System.out.println(a[i]);
            }
        }
    }
    

    【讨论】:

    • 说什么...这不会有任何区别
    • 你是对的,这和我之前的代码做的一样。
    • 更新了我的解决方案。现在可以使用了。不确定您是只想打印它们还是让它们退回。此解决方案会打印它们。
    • 呃这个解决方案打印模式的次数,而我希望它只打印一次。谢谢,不过现在我大致了解了这段代码的工作原理。
    【解决方案4】:

    希望这会有所帮助。这是我的回答。希望对你有帮助

    public List mode(double[] m) {
        HashMap<Double, Double> freqs = new HashMap<Double, Double>();
        for (double d : m) {
            Double freq = freqs.get(d);
            freqs.put(d, (freq == null ? 1 : freq + 1));
        }
        List<Double> mode = new ArrayList<Double>();
        List<Double> frequency = new ArrayList<Double>();
        List<Double> values = new ArrayList<Double>();
    
        for (Map.Entry<Double, Double> entry : freqs.entrySet()) {
            frequency.add(entry.getValue());
            values.add(entry.getKey());
        }
        double max = Collections.max(frequency);
    
        for(int i=0; i< frequency.size();i++)
        {
            double val =frequency.get(i);
            if(max == val )
            {
                mode.add(values.get(i));
            }
        }
        return mode;
    }
    

    【讨论】:

      【解决方案5】:

      处理多个模式值: 最初,我正在绘制一张地图来获取每个元素的频率。在找到最大重复值后,我正在存储它的地图值。 在迭代地图时,我正在检查该值是否对某个键重复并且不是 1,如果是,那么我也添加该键。这将为我提供多种模式

      public static void mode(int a[]){
      
          int count=0;
          Map<Integer,Integer> map=new HashMap<>();
          for(int i=0;i<a.length;i++)
          {
              map.put(a[i],map.getOrDefault(a[i],0)+1);
          }
          Set<Integer> set=new HashSet<>();
          int maxValue=0;
          for(int i=0;i<a.length;i++)
          {
              int ct=0;
              for(int j=0;j<a.length;j++)
              {
                  if(a[i]==a[j])
                      ct++;
              }
              if(ct>count)
              {
                  count=ct;
                  maxValue=a[i];
              }
              
          }
          set.add(maxValue);
          int k=map.get(maxValue);
          if(k!=1)
          {
          for(Map.Entry m:map.entrySet())
          {
              if((int)m.getValue()==k)
                  set.add((int)m.getKey());
          }
          }
          System.out.println("Mode: "+set);
          
      }
      

      【讨论】:

        猜你喜欢
        • 2014-01-28
        • 1970-01-01
        • 1970-01-01
        • 2013-02-21
        • 2021-07-27
        • 1970-01-01
        • 2012-07-10
        • 2017-07-18
        • 1970-01-01
        相关资源
        最近更新 更多