【发布时间】:2010-09-11 17:33:24
【问题描述】:
我想知道是否可以找到数组的中值?例如,假设我有一个大小为 9 的数组。能找到这个数组的中间槽吗?
【问题讨论】:
-
如果您对数组处理有所了解,那应该是非常简单的。请注意,除非数组已排序,否则中间槽不是中位数。这是作业吗?
-
Java 还是 C++?选一个。而且“中值”和“中槽”不是一回事,选一个吧。
我想知道是否可以找到数组的中值?例如,假设我有一个大小为 9 的数组。能找到这个数组的中间槽吗?
【问题讨论】:
假设数组 x 已排序且长度为 n:
如果 n 为奇数,则中位数为 x[(n-1)/2]。
如果 n 比中位数为偶数,则为 ( x[n/2] + x[(n/2)-1] ) / 2。
【讨论】:
如果你想在这里使用任何外部库是Apache commons math library,你可以计算Median。
更多方法和使用请看API documentation
import org.apache.commons.math3.*;
.....
......
........
//calculate median
public double getMedian(double[] values){
Median median = new Median();
double medianValue = median.evaluate(values);
return medianValue;
}
.......
在程序中计算
一般情况下,中位数的计算使用以下两个公式given here
如果 n 是奇数,则中位数 (M) = 第 ((n + 1)/2) 项的值。
如果 n 为偶数,则中位数 (M) = [((n)/2)th item term + ((n)/2 + 1)th item term ]/2
这很容易,因为你有 9 个元素(奇数)。
查找数组的中间元素。
在你的程序中你可以声明数组
//as you mentioned in question, you have array with 9 elements
int[] numArray = new int[9];
那么你需要使用Arrays#sort对数组进行排序
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;
【讨论】:
在 C++ 中,您可以使用std::nth_element;见http://cplusplus.com/reference/algorithm/nth_element/。
【讨论】:
在java中:
int middleSlot = youArray.length/2;
yourArray[middleSlot];
或
yourArray[yourArray.length/2];
一行。
这是可能的,因为在 java 中数组具有固定大小。
注意: 3/2 == 1
资源:
【讨论】:
vector<int> v;
size_t len = v.size;
nth_element( v.begin(), v.begin()+len/2,v.end() );
int median = v[len/2];
【讨论】:
像专业人士一样在一行中完成:
return (arr[size/2] + arr[(size-1)/2]) / 2;
如果您期待 double 等,请转换为 double 等。
【讨论】:
上面的 Java 答案只有在有奇数数量的数字时才有效,这是我得到的解决方案的答案:
if (yourArray.length % 2 == 0){
//this is for if your array has an even ammount of numbers
double middleNumOne = yourArray[yourArray.length / 2 - 0.5]
double middleNumTwo = yourArray[yourArray.length / 2 + 0.5]
double median = (middleNumOne + middleNumTwo) / 2;
System.out.print(median);
}else{
//this is for if your array has an odd ammount of numbers
System.out.print(yourArray[yourArray.length/2];);
}
请注意,这是一个概念证明,而且是即时的。如果你认为你可以让它更紧凑或更不密集,那就继续吧。请不要批评它。
【讨论】:
还有另一种选择——一般来说,这里的建议要么建议对数组进行排序,然后从这样的数组中获取中值,要么依赖于(外部)库解决方案。当今最快的排序算法平均而言是线性的,但在计算中值时可能会比线性算法做得更好。
从未排序的数组中计算中位数的最快算法是QuickSelect,平均而言,它可以在与 O(N) 成正比的时间内找到中位数。该算法将数组作为参数,以及 int 值k(顺序统计,即数组中的第 k 个最小元素)。在这种情况下,k 的值只是 N/2,其中 N 是数组长度。
实现起来有点棘手,但这里有一个示例,它依赖于Comparable<T> 接口和Collections.shuffle(),没有任何外部依赖。
public final class QuickSelectExample {
public static <T extends Comparable<? super T>> T select(T[] a, int k) {
if (k < 1) throw new IllegalStateException("Invalid k - must be in [1, inputLength].");
if (k > a.length) throw new IllegalStateException("K-th element exceeds array length.");
Collections.shuffle(Arrays.asList(a));
return find(a, 0, a.length - 1, k - 1);
}
private static <T extends Comparable<? super T>> T find(T[] a, int lo, int hi, int k) {
int mid = partition(a, lo, hi);
if (k == mid) return a[k];
else if (k < mid) return find(a, lo, mid - 1, k); // search left subarray
else if (k > mid) return find(a, mid + 1, hi, k); // search right subarray
else throw new IllegalStateException("Not found");
}
private static <T extends Comparable<? super T>> int partition(T[] a, int lo, int hi) {
T pivot = a[lo];
int i = lo + 1;
int j = hi;
while (true) { // phase 1
while (i <= hi && (less(a[i], pivot) || eq(a[i], pivot))) // is a[i] >= pivot?
i++;
while (j >= i && !less(a[j], pivot)) // is a[j] <= pivot?
j--;
if (i >= j) break;
exch(a, i, j);
}
exch(a, lo, j); // phase 2
return j;
}
private static <T extends Comparable<? super T>> boolean less(T x, T y) {
return x.compareTo(y) < 0;
}
private static <T extends Comparable<? super T>> boolean eq(T x, T y) {
return x.compareTo(y) == 0;
}
}
代码为这些输入数组生成以下顺序统计信息:
" Input Array | Actual Output [format: (index k -> array element)] ", //
" | ", //
" [S, O, R, T, E, X, A, M, P, L, E] | [(1 -> A), (2 -> E), (3 -> E), (4 -> L), (5 -> M), (6 -> O), (7 -> P), (8 -> R), (9 -> S), (10 -> T), (11 -> X)] ", //
" [P, A, B, X, W, P, P, V, P, D, P, C, Y, Z] | [(1 -> A), (2 -> B), (3 -> C), (4 -> D), (5 -> P), (6 -> P), (7 -> P), (8 -> P), (9 -> P), (10 -> V), (11 -> W), (12 -> X), (13 -> Y), (14 -> Z)] " //
【讨论】:
在 Java 的情况下,除以 2.0 足以将 int 转换为 double:
return n%2 == 0 ? (all[n/2] + all[n/2-1])/2.0 : all[(n-1)/2];
第一个条件检查值是否为偶数。
【讨论】: