我有一个1000的数组。如何找到五个最大元素的索引(索引)?
设置代码和我的尝试的示例如下所示:
Random rand = new Random();
int[] myArray = new int[1000];
int[] maxIndices = new int[5];
int[] maxValues = new int[5];
for (int i = 0; i < myArray.length; i++) {
myArray[i] = rand.nextInt();
}
for (int i = 0; i < 5; i++) {
maxIndices[i] = i;
maxValues[i] = myArray[i];
}
for (int i = 0; i < maxIndices.length; i++) {
for (int j = 0; j < myArray.length; j++) {
if (myArray[j] > maxValues[i]) {
maxIndices[i] = j;
maxValues[i] = myArray[j];
}
}
}
for (int i = 0; i < maxIndices.length; i++) {
System.out.println("Index: " + maxIndices[i]);
}
我知道问题在于它不断地为所有最大元素分配最高的最大值。我不确定如何解决这个问题,因为我必须保留myArray
的值和索引。
我不认为排序是一种选择,因为我需要保留索引。事实上,这是我需要的指标。
答案 0 :(得分:7)
排序是一种选择,代价是额外的内存。请考虑以下算法。
1. Allocate additional array and copy into - O(n)
2. Sort additional array - O(n lg n)
3. Lop off the top k elements (in this case 5) - O(n), since k could be up to n
4. Iterate over the original array - O(n)
4.a search the top k elements for to see if they contain the current element - O(lg n)
所以第4步是(n * lg n),就像排序一样。整个算法都是n lg n,编码非常简单。
这是一个快速而肮脏的例子。可能存在错误,显然无效检查等等。
import java.util.Arrays;
class ArrayTest {
public static void main(String[] args) {
int[] arr = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
int[] indexes = indexesOfTopElements(arr,3);
for(int i = 0; i < indexes.length; i++) {
int index = indexes[i];
System.out.println(index + " " + arr[index]);
}
}
static int[] indexesOfTopElements(int[] orig, int nummax) {
int[] copy = Arrays.copyOf(orig,orig.length);
Arrays.sort(copy);
int[] honey = Arrays.copyOfRange(copy,copy.length - nummax, copy.length);
int[] result = new int[nummax];
int resultPos = 0;
for(int i = 0; i < orig.length; i++) {
int onTrial = orig[i];
int index = Arrays.binarySearch(honey,onTrial);
if(index < 0) continue;
result[resultPos++] = i;
}
return result;
}
}
您可以采取其他措施来减少此操作的开销。例如,您可以选择使用仅跟踪最大5的队列而不是排序。由于int
s,它们的值可能必须被加框以添加到集合中(除非您自己滚动)添加显着开销。
答案 1 :(得分:3)
/**
* Return the indexes correspond to the top-k largest in an array.
*/
public static int[] maxKIndex(double[] array, int top_k) {
double[] max = new double[top_k];
int[] maxIndex = new int[top_k];
Arrays.fill(max, Double.NEGATIVE_INFINITY);
Arrays.fill(maxIndex, -1);
top: for(int i = 0; i < array.length; i++) {
for(int j = 0; j < top_k; j++) {
if(array[i] > max[j]) {
for(int x = top_k - 1; x > j; x--) {
maxIndex[x] = maxIndex[x-1]; max[x] = max[x-1];
}
maxIndex[j] = i; max[j] = array[i];
continue top;
}
}
}
return maxIndex;
}
答案 2 :(得分:1)
很抱歉回答这个老问题,但是我缺少具有以下所有属性的实现:
因此,我实现了它:
private int[] getBestKIndices(float[] array, int num) {
//create sort able array with index and value pair
IndexValuePair[] pairs = new IndexValuePair[array.length];
for (int i = 0; i < array.length; i++) {
pairs[i] = new IndexValuePair(i, array[i]);
}
//sort
Arrays.sort(pairs, new Comparator<IndexValuePair>() {
public int compare(IndexValuePair o1, IndexValuePair o2) {
return Float.compare(o2.value, o1.value);
}
});
//extract the indices
int[] result = new int[num];
for (int i = 0; i < num; i++) {
result[i] = pairs[i].index;
}
return result;
}
private class IndexValuePair {
private int index;
private float value;
public IndexValuePair(int index, float value) {
this.index = index;
this.value = value;
}
}
答案 3 :(得分:0)
Arrays.sort(myArray),然后取最后的5个元素。
如果要保留原始订单,请对副本进行排序。
如果你想要索引,那么就没有像python或其他语言那样的快速解决方案。你排序和扫描,但这很难看。
或者你可以去反对 - 毕竟这是java。 创建一个ArrayMaxFilter对象。它将有一个私有类ArrayElement,它由一个索引和一个值组成,并按值自然排序。它将有一个方法,它接受一对int,index和value,创建它们的ArrayElement,并将它们放入长度为5的优先级队列中(或者你想要找到多少)。从数组中提交每个索引/值对,然后报告队列中剩余的值。 (是的,优先级队列传统上保留最低值,但您可以在实现中将其翻转)
答案 4 :(得分:0)
我的快速和一点点“在盒子外思考”的想法是使用最多包含5个元素的EvictingQueue
。您必须使用数组中的前五个元素预先填充它(按升序执行,因此您添加的第一个元素是五个中最低的元素)。
每当当前值大于队列中的最小值时,您必须迭代数组并向队列添加新元素。要记住索引,请创建包装器对象(值/索引对)。
在遍历整个数组之后,队列中有五个最大值/索引对(按降序排列)。
这是一个O(n)解决方案。
答案 5 :(得分:0)
这是我的解决方案。创建一个将indice与值配对的类:
public class IndiceValuePair{
private int indice;
private int value;
public IndiceValuePair(int ind, int val){
indice = ind;
value = val;
}
public int getIndice(){
return indice;
}
public int getValue(){
return value;
}
}
然后在main方法中使用此类:
public static void main(String[] args){
Random rand = new Random();
int[] myArray = new int[10];
IndiceValuePair[] pairs = new IndiceValuePair[5];
System.out.println("Here are the indices and their values:");
for(int i = 0; i < myArray.length; i++) {
myArray[i] = rand.nextInt(100);
System.out.println(i+ ": " + myArray[i]);
for(int j = 0; j < pairs.length; j++){
//for the first five entries
if(pairs[j] == null){
pairs[j] = new IndiceValuePair(i, myArray[i]);
break;
}
else if(pairs[j].getValue() < myArray[i]){
//inserts the new pair into its correct spot
for(int k = 4; k > j; k--){
pairs[k] = pairs [k-1];
}
pairs[j] = new IndiceValuePair(i, myArray[i]);
break;
}
}
}
System.out.println("\n5 Max indices and their values");
for(int i = 0; i < pairs.length; i++){
System.out.println(pairs[i].getIndice() + ": " + pairs[i].getValue());
}
}
和运行的示例输出:
Here are the indices and their values:
0: 13
1: 71
2: 45
3: 38
4: 43
5: 9
6: 4
7: 5
8: 59
9: 60
5 Max indices and their values
1: 71
9: 60
8: 59
2: 45
4: 43
我提供的示例只生成10个整数,其值介于0到99之间,这样我才能看到它有效。您可以轻松更改此值以适应任何大小的1000个值。另外,我没有运行3个单独的for循环,而是在添加到myArray
之后检查我添加的最新值是否为最大值。给它一个运行,看看它是否适合你