获取数组中 n 个最小元素的索引

Posted

技术标签:

【中文标题】获取数组中 n 个最小元素的索引【英文标题】:get indexes of n smallest elements in an array 【发布时间】:2011-02-16 13:45:20 【问题描述】:

我有一个 int 数组 int[] myArray = new int[100]; 并且想要获取最小 10(任意 n)个元素的索引。我该怎么做?

【问题讨论】:

如果您展示了您的尝试,这将有助于社区提供更好的帮助。具体来说,如果您正在尝试某些代码并且它运行不正常,最好向我们展示似乎无法正常运行的 sn-p。 @erasmus 他在问这是否用于家庭作业。标记为作业的问题会收到不同的答案。例如 How do I sort an array with [homework] tag 将导致对不同排序算法的解释,没有它,将得到Arrays.sort( list ); @Oscar,我不认为他是真诚的。像他这样的人也有。他们所做的是降低问题的投票值并编写一些挑衅性的 cmets。那些家伙只是没用的东西。 @erasmus:有时问题以不清楚的方式发布。我不得不读了好几遍,因为我不太明白。我添加了我的答案,看看是不是你需要的。 @erasmus:我必须同意 Oscar 的观点——这个问题在我看来是一个家庭作业式的问题。 【参考方案1】:

排序数组然后选择 10 很简单,但它会是 O(n log n),如果你不想重新排序初始数组,你也需要复制一份。

一个更好的主意是使用最大堆(或优先级队列),它会在您插入元素时自动对元素进行排序,这样最大的元素就是根节点。沿着数组走,继续放入元素,直到达到 10;然后,对于每个后续元素,只需检查它是否小于堆中最大的元素(恒定时间检查),如果是,则将其弹出并插入新元素。当你遍历整个数组时,里面剩下的 10 个东西就是你的最小元素。这会让你得到 O(n log 10) == O(n) 的结果,因为每次插入堆只花费 O(log 10)。

Java 的 Priority Queue 实现默认是最小队列,因此您需要传入一个反转排序的 Comparator。有关如何执行此操作的示例,请参阅this question。如果您想在最后获取索引,您还需要创建一个包含 (value, index) 对的自定义对象。

【讨论】:

【参考方案2】:

创建一个包含数字和索引的对象,然后创建这些对象的数组,然后执行 Array.Sort(arrayset[],comparator)java docs。然后你就可以从排序后的数组中挑选出前 x 项。

编辑: 像这样的东西...... [我用这个根据'距离'进行排序

import java.util.Arrays;
import java.util.Comparator;

public class NearestObject

    public NearestObject(int position, int distance)
    
         this.Position = position;
         this.Distance = distance;
    
    public int Position = 0;
    public int Distance = 0;

    public static NearestObject[] SortDistance(NearestObject[] items)
    
        Arrays.sort(items, new DistanceSort());
        return items;
    



class DistanceSort implements Comparator<NearestObject>

    public int compare(NearestObject o1, NearestObject o2)
    
        return o1.Distance - o2.Distance;
    

【讨论】:

【参考方案3】:

直接的解决方案是遍历数组并维护您找到的 n 个最小元素及其索引的列表。这是一个 O(N) 的解决方案,在大多数情况下都可以接受。我猜这是家庭作业,你必须有比 O(N) 更好的东西。

【讨论】:

不是 O(n*m) 吗? (n=输入大小,m=项目数) @Kurru,诚然,我的回答的细节并不完全清楚。我认为这个问题以前被标记为作业。我不认为它是 O(NM) 因为不必遍历 M 元素的列表。一旦找到第 M 个最小的元素,N 列表上的所有后续迭代只需要根据第 M 个元素检查自己。我认为最好通过使用优先级堆来促进这种行为。所以... O(Nlog(M)) ??? 所以我想我的答案只是@tzaman 答案的描述性较差的版本。 优先级循环是否在最坏的情况下插入和读取日志(M)?不知道 在读取堆时,通常会关注最小值或最大值,实现通常允许 O(1) 的读取复杂度。插入/删除复杂度为 O(logN)。这是 Java 的 PriorityQueue:download.oracle.com/javase/6/docs/api/java/util/… 该类的 javadoc 的最后一行描述了当前实现所保证的时间复杂度。【参考方案4】:

按索引排序并返回前 10 个

首先创建一个结构来保存索引和值:

class IndexValue 
   final int i;
   final int v;

然后用这个新结构创建一个数组:

IndexValue[] array = new IndexValue[myArray.length];
for( int i = 0 ; i < array.length ; i++ ) 
    array[i] = new IndexValue( i, myArray[i] );

最后排序,取前N个元素

Arrays.sort( array ); // you'll need to implement Comparator though 

for( int i = 0 ; i< 10 ;i++ ) 
    System.out.print( array[i] );

这是完整的工作代码:

import java.util.Arrays;
import java.util.Random;
import java.util.Comparator;
import static java.lang.System.out;

class IndexValue 
   final int i,v;

   public IndexValue( int i, int v ) 
       this.i = i;
       this.v = v;
   

public class SortByIndex 
    public static void main( String [] args ) 

        Random random = new Random();

        int [] myArray = new int[100];
        IndexValue[] array = new IndexValue[myArray.length];

        // Fill the array 
        for( int i = 0 ; i < 100; i++ ) 
            myArray[i] = random.nextInt();
            array[i] = new IndexValue( i, myArray[i] );
        

        // Sort it 
        Arrays.sort( array, new Comparator<IndexValue>()
            public int compare( IndexValue a, IndexValue b )
                return a.v - b.v;
            
        );

        // Print it
        out.println("Top:");
        for( int i = 0 ; i < 10 ; i++ ) 
            out.println( String.format("array[%d]=%d",  array[i].i, array[i].v ));
        

    

【讨论】:

【参考方案5】:

您可以对数组进行排序,循环前 10 个元素,然后为每个元素在数组中搜索它所在的位置...也许这不是更有效的方法,但它更容易。

【讨论】:

【参考方案6】:

如果您正在寻找一个实用的答案(相对于实际的排序算法等),那么只需使用 HashMap 或 PriorityQueue。如果速度不是问题,试试这个简单的算法。它比 PriorityQueue 更容易,因为您不需要自定义对象:

HashMap&lt;Integer, ArrayList&lt;Integer&gt;&gt; indexMap = new HashMap&lt;Integer, ArrayList&lt;Integer&gt;&gt;();

填写 indexMap 以便我们可以获取数组中任何给定数字的索引

for (int index = 0; index <= array.size; index++) 
   if (indexMap.get(array[index]) == null)  // Prime it with an ArrayList
      indexMap.put(array[index], new ArrayList<Integer>());
   

   indexMap.get(array[index]).add(index);

对于数组中最小的 n 个数,打印出它们的索引。

Arrays.sort(array);
for (int index = 0; index <= n; index++) 
   System.out.println(indexMap.get(array[index]).remove(0));

【讨论】:

以上是关于获取数组中 n 个最小元素的索引的主要内容,如果未能解决你的问题,请参考以下文章

Python | 快速获取某一列数组中前 N 个最大值/最小值的索引 | 三种方法总结

忽略数组中的元素值时获取最小索引

获取java数组中n个最大值的索引

获取R中矩阵每一行中K个最小或最大元素的索引

numpy数组列表中N个最高元素的索引[重复]

确定数组中 N 个非零最小值的索引