在Java中编写一种方法,以查找数组中出现频率最高的元素。

16

问题是:

编写一个名为mode的方法,该方法返回整数数组中出现频率最高的元素。假设数组至少有一个元素,并且数组中的每个元素的值介于0和100之间(包括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;,现在一切都正常了!


3
在提问之前对好的工作进行加1评价(几乎可以胜任,除了单元素数组的情况)。你能否将你的解决方案发布为答案并将其标记为正确?这样其他人就不会来到你的问题帮助你,认为它还没有被回答。谢谢。 - Simon
我赞同@Simon的评论,并补充说目前被接受的答案(Gubatron的)是有缺陷和不正确的。例如,它将无法处理示例输入{27,15,15,11,27}counts的长度为5,行counts [n [I]] ++将失败,因为它将尝试增加索引为27的元素,如shridhad在评论中指出的越界了。 - phoog
我同意Simon的看法,您能把编辑好的解决方案移动到下面的回答中吗?我们喜欢在这里使用问答格式。 - halfer
1
回顾这个问题,五年后的今天,我惊讶于自己的成长。那时候,我刚开始转行计算机科学,对于像 mapset 这样的数据结构一无所知。在学习和工作中,我通过几乎蛮力的方法探索了高效的算法。这改变了我的人生 :) - TonyGW
14个回答

0

我最近编写了一个程序,可以计算一些不同的统计数据,包括众数。虽然编码可能很基础,但它适用于任何整数数组,并且可以修改为双精度、浮点数等。对数组的修改是基于删除数组中不是最终众数值的索引。这允许您显示所有模式(如果有多个),以及具有出现次数(模式数组中的最后一项)。下面的代码是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;
}

0

基于 @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));
    }
}

0
import java.util.HashMap;

public class SmallestHighestRepeatedNumber {
    static 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;
    }
}

你能提供一些上下文吗? - Nico Haase
你只是复制粘贴了我的答案,伙计。 - codemania23

-2

这段代码计算众数、中位数和平均数。它已经过测试并且可以正常工作。这是一个从头到尾的完整程序,可以编译。

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();
    }

}

2
我没有点踩,但是你的模式算法非常低效。你试过输入 1000000 吗? - phoog
没有,我没有这样做...至少我的代码足够简单,让普通低级程序员可以理解和实现... - Mason Smart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接