我正在尝试计算由文本字段接收的输入填充的数组的总数,平均值和中位数。我已经设法计算出总数和均值,我只是无法得到中位数。我认为在我能做到这一点之前需要对数组进行排序,但我不知道如何做到这一点。这是问题,还是有另一个我没找到的?这是我的代码:
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.*;
public class whileloopq extends Applet implements ActionListener
{
Label label;
TextField input;
int num;
int index;
int[] numArray = new int[20];
int sum;
int total;
double avg;
int median;
public void init ()
{
label = new Label("Enter numbers");
input = new TextField(5);
add(label);
add(input);
input.addActionListener(this);
index = 0;
}
public void actionPerformed (ActionEvent ev)
{
int num = Integer.parseInt(input.getText());
numArray[index] = num;
index++;
if (index == 20)
input.setEnabled(false);
input.setText("");
sum = 0;
for (int i = 0; i < numArray.length; i++)
{
sum += numArray[i];
}
total = sum;
avg = total / index;
median = numArray[numArray.length/2];
repaint();
}
public void paint (Graphics graf)
{
graf.drawString("Total = " + Integer.toString(total), 25, 85);
graf.drawString("Average = " + Double.toString(avg), 25, 100);
graf.drawString("Median = " + Integer.toString(median), 25, 115);
}
}
答案 0 :(得分:56)
Java中的Arrays类有一个静态排序函数,您可以使用Arrays.sort(numArray)
调用它。
Arrays.sort(numArray);
double median;
if (numArray.length % 2 == 0)
median = ((double)numArray[numArray.length/2] + (double)numArray[numArray.length/2 - 1])/2;
else
median = (double) numArray[numArray.length/2];
答案 1 :(得分:30)
对数组进行排序是不必要且效率低下的。有一种QuickSort(QuickSelect)算法的变体,其平均运行时间为O(n);如果你先排序,那么你就是O(n log n)。它实际上找到了列表中的第n个最小项;对于中位数,您只需使用n =列表长度的一半。我们称之为quickNth(list,n)。
概念是找到第n个最小值,选择一个'pivot'值。 (具体如何选择它并不重要;如果您知道数据将是完全随机的,您可以选择列表中的第一项。)
将原始列表拆分为三个较小的列表:
然后您有三种情况:
完成。
如果您不确定数据是否完全随机,则需要更加精确地选择枢轴。取列表中第一个值的中位数,列表中的最后一个值,以及两个中间值之间的值非常好。
如果您对选择的枢轴非常不走运,并且总是选择最小值或最高值作为枢轴,则需要O(n ^ 2)时间;那很糟。但是,如果您选择具有合适算法的支点,那么它也非常。
答案 2 :(得分:6)
如果您想在Apache commons math library使用任何外部库,可以使用Median来计算API documentation。 有关更多方法和用法,请查看AbstractUnivariateStatistic#evaluate
import org.apache.commons.math3.*;
.....
......
........
//calculate median
public double getMedian(double[] values){
Median median = new Median();
double medianValue = median.evaluate(values);
return medianValue;
}
.......
更新
在程序中计算
通常,使用以下两个公式Arrays#sort
计算中位数如果n为奇数,则中位数(M)=((n + 1)/ 2)项项的值。
如果n是偶数,那么中位数(M)= [((n)/ 2)项项的值+((n)/ 2 + 1)项项] / 2
在您的程序中,您有numArray
,首先需要使用{{3}}对数组进行排序
Arrays.sort(numArray);
int middle = numArray.length/2;
int medianValue = 0; //declare variable
if (numArray.length%2 == 1)
medianValue = numArray[middle];
else
medianValue = (numArray[middle-1] + numArray[middle]) / 2;
答案 3 :(得分:4)
Arrays.sort(numArray);
int middle = ((numArray.length) / 2);
if(numArray.length % 2 == 0){
int medianA = numArray[middle];
int medianB = numArray[middle-1];
median = (medianA + medianB) / 2;
} else{
median = numArray[middle + 1];
}
编辑:我最初在偶数长度数组中将medianB
设置为middle+1
,这是错误的,因为数组从0开始计数。我已将其更新为使用middle-1
,这是正确并且应该适用于长度均匀的数组。
答案 4 :(得分:2)
首先尝试排序数组。然后在它排序之后,如果数组具有偶数元素,则中间两个的平均值是中位数,如果它具有奇数,则中间元素是中位数。
答案 5 :(得分:1)
使用Arrays.sort
然后取中间元素(如果数组中元素的数量n
为奇数)或取两个中间元素的平均值(以防n
}甚至)。
public static long median(long[] l)
{
Arrays.sort(l);
int middle = l.length / 2;
if (l.length % 2 == 0)
{
long left = l[middle - 1];
long right = l[middle];
return (left + right) / 2;
}
else
{
return l[middle];
}
}
以下是一些例子:
@Test
public void evenTest()
{
long[] l = {
5, 6, 1, 3, 2
};
Assert.assertEquals((3 + 4) / 2, median(l));
}
@Test
public oddTest()
{
long[] l = {
5, 1, 3, 2, 4
};
Assert.assertEquals(3, median(l));
}
如果您的输入是Collection
,您可以使用Google Guava执行以下操作:
public static long median(Collection<Long> numbers)
{
return median(Longs.toArray(numbers)); // requires import com.google.common.primitives.Longs;
}
答案 6 :(得分:1)
昨天我遇到了类似的问题。 我用Java泛型编写了一个方法来计算每个数字集合的中值;你可以将我的方法应用于Doubles,Integers,Floats的集合并返回一个double。请考虑我的方法创建另一个集合,以便不改变原始集合。 我也提供测试,玩得开心。 ; - )
public static <T extends Number & Comparable<T>> double median(Collection<T> numbers){
if(numbers.isEmpty()){
throw new IllegalArgumentException("Cannot compute median on empty collection of numbers");
}
List<T> numbersList = new ArrayList<>(numbers);
Collections.sort(numbersList);
int middle = numbersList.size()/2;
if(numbersList.size() % 2 == 0){
return 0.5 * (numbersList.get(middle).doubleValue() + numbersList.get(middle-1).doubleValue());
} else {
return numbersList.get(middle).doubleValue();
}
}
JUnit测试代码段:
/**
* Test of median method, of class Utils.
*/
@Test
public void testMedian() {
System.out.println("median");
Double expResult = 3.0;
Double result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,13.0));
assertEquals(expResult, result);
expResult = 3.5;
result = Utils.median(Arrays.asList(3.0,2.0,1.0,9.0,4.0,13.0));
assertEquals(expResult, result);
}
用法示例(考虑类名为Utils):
List<Integer> intValues = ... //omitted init
Set<Float> floatValues = ... //omitted init
.....
double intListMedian = Utils.median(intValues);
double floatSetMedian = Utils.median(floatValues);
注意:我的方法适用于集合,您可以将数字数组转换为指向here的数字列表
答案 7 :(得分:1)
我在看同样的统计问题。你认为它的方法是好的,它会起作用。 (已经给出了排序的答案)
但是如果您对算法性能感兴趣,我认为有一些算法比仅仅对数组进行排序有更好的性能,其中一个(QuickSelect)由@bruce-feist的回答表示,非常很好地解释了。
[Java实现:https://discuss.leetcode.com/topic/14611/java-quick-select]
但是这个算法有一个名为median of medians的变体,你可以在这个链接上找到一个很好的解释: http://austinrochford.com/posts/2013-10-28-median-of-medians.html
这个的Java实现: - https://stackoverflow.com/a/27719796/957979
答案 8 :(得分:1)
您可以在https://www.youtube.com/watch?time_continue=23&v=VmogG01IjYc
找到合适的解释它使用2堆的想法即一个最大堆和平均堆。
class Heap {
private Queue<Integer> low = new PriorityQueue<>(Comparator.reverseOrder());
private Queue<Integer> high = new PriorityQueue<>();
public void add(int number) {
Queue<Integer> target = low.size() <= high.size() ? low : high;
target.add(number);
balance();
}
private void balance() {
while(!low.isEmpty() && !high.isEmpty() && low.peek() > high.peek()) {
Integer lowHead= low.poll();
Integer highHead = high.poll();
low.add(highHead);
high.add(lowHead);
}
}
public double median() {
if(low.isEmpty() && high.isEmpty()) {
throw new IllegalStateException("Heap is empty");
} else {
return low.size() == high.size() ? (low.peek() + high.peek()) / 2.0 : low.peek();
}
}
}
答案 9 :(得分:0)
查看Arrays.sort方法:
http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html
你也应该抽象地将中位数找到它自己的方法中,然后将值返回给调用方法。这将使您的代码测试变得更加容易。
答案 10 :(得分:0)
public int[] data={31, 29, 47, 48, 23, 30, 21
, 40, 23, 39, 47, 47, 42, 44, 23, 26, 44, 32, 20, 40};
public double median()
{
Arrays.sort(this.data);
double result=0;
int size=this.data.length;
if(size%2==1)
{
result=data[((size-1)/2)+1];
System.out.println(" uneven size : "+result);
}
else
{
int middle_pair_first_index =(size-1)/2;
result=(data[middle_pair_first_index+1]+data[middle_pair_first_index])/2;
System.out.println(" Even size : "+result);
}
return result;
}
答案 11 :(得分:0)
Arrays.sort(numArray);
return (numArray[size/2] + numArray[(size-1)/2]) / 2;
答案 12 :(得分:0)
当list仅包含一个元素(list.size == 1)时,没有人注意。您的所有答案都将因索引超出范围的异常而崩溃,因为整数除法返回零(1/2 = 0)。正确答案(在Kotlin中):
MEDIAN("MEDIAN") {
override fun calculate(values: List<BigDecimal>): BigDecimal? {
if (values.size == 1) {
return values.first()
}
if (values.size > 1) {
val valuesSorted = values.sorted()
val mid = valuesSorted.size / 2
return if (valuesSorted.size % 2 != 0) {
valuesSorted[mid]
} else {
AVERAGE.calculate(listOf(valuesSorted[mid - 1], valuesSorted[mid]))
}
}
return null
}
},
答案 13 :(得分:0)
正如@ Bruce-Feist提到的那样,对于许多元素,如果您担心性能,我会避免使用任何涉及排序的解决方案。与其他答案中建议的方法不同的是Hoare算法,该算法可找到n个元素的第k个最小元素。该算法在O(n)中运行。
public int findKthSmallest(int[] array, int k)
{
if (array.length < 10)
{
Arrays.sort(array);
return array[k];
}
int start = 0;
int end = array.length - 1;
int x, temp;
int i, j;
while (start < end)
{
x = array[k];
i = start;
j = end;
do
{
while (array[i] < x)
i++;
while (x < array[j])
j--;
if (i <= j)
{
temp = array[i];
array[i] = array[j];
array[j] = temp;
i++;
j--;
}
} while (i <= j);
if (j < k)
start = i;
if (k < i)
end = j;
}
return array[k];
}
并找到中位数:
public int median(int[] array)
{
int length = array.length;
if ((length & 1) == 0) // even
return (findKthSmallest(array, array.length / 2) + findKthSmallest(array, array.length / 2 + 1)) / 2;
else // odd
return findKthSmallest(array, array.length / 2);
}
答案 14 :(得分:0)
public static int median(int[] arr) {
int median = 0;
java.util.Arrays.sort(arr);
for (int i=0;i<arr.length;i++) {
if (arr.length % 2 == 1) {
median = Math.round(arr[arr.length/2]);
} else {
median = (arr[(arr.length/2)] + arr[(arr.length/2)-1])/2;
}
}
return median;
}