簡體   English   中英

獲取java數組中n個最大值的索引

[英]Get indices of n maximums in java array

我有一個大小為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的值和索引。

我不認為排序是一種選擇,因為我需要保留索引。 事實上,這是我需要的指標。

排序是一種選擇,以額外的內存為代價。 考慮以下算法。

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它們的值可能必須被加框以添加到集合中(除非您自己滾動),這顯着增加了開銷。

回答有點晚,你也可以使用我寫的這個函數:

/**
  * 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;
}

很抱歉回答這個老問題,但我錯過了一個具有以下所有屬性的實現:

  • 易於閱讀
  • 高性能
  • 處理多個相同的值

因此我實現了它:

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

Arrays.sort(myArray),然后取最后的5個元素。

如果要保留原始訂單,請對副本進行排序。

如果你想要索引,就沒有像python或其他語言那樣的快速解決方案。 你排序和掃描,但這很難看。

或者你可能會變得粗魯 - 畢竟這是java。 創建一個ArrayMaxFilter對象。 它將有一個私有類ArrayElement,它由一個索引和一個值組成,並按值自然排序。 它將有一個方法,它接受一對int,index和value,創建它們的ArrayElement,並將它們放入長度為5的優先級隊列中(或者你想要找到多少)。 從數組中提交每個索引/值對,然后報告隊列中剩余的值。 (是的,優先級隊列傳統上保持最低值,但您可以在實現中將其翻轉)

我的快速和有點“開箱即用”的想法是使用最多包含5個元素的EvictingQueue 您必須使用數組中的前五個元素預先填充它(按升序執行,因此您添加的第一個元素是五個中最低的元素)。

每當當前值大於隊列中的最小值時,您必須迭代數組並向隊列添加新元素。 要記住索引,請創建包裝器對象(值/索引對)。

在遍歷整個數組之后,隊列中有五個最大值/索引對(按降序排列)。

這是一個O(n)解決方案。

這是我的解決方案。 創建一個將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之后檢查我添加的最新值是否為最大值。 給它一個運行,看看它是否適合你

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM