如何从数组中返回最小的整数?

时间:2013-09-17 16:08:33

标签: java arrays algorithm sorting methods

我有一个数组int [] a = {5,3,1,2}并且我想创建一个方法来选出“k”个最小数字并返回一个数字,其中k个最小整数按升序排列。但是当我运行这段代码时,我得到了输出:[1,3]。 我知道代码以某种方式跳过某些数字,但我无法扭曲我的大脑来修复它。 有什么想法吗?

编辑:不对原始数组进行排序。

 public static int[] nrSmallest(int[] a, int k)  {
            if(k <1 || k>a.length)
                throw new IllegalArgumentException("must be at least 1");
            int[] values= Arrays.copyOf(a, k);
            Arrays.sort(values);
            int counter= 0;  
                for(int i= k; i < a.length; i++)    {
                        if(a[i]< values[counter])   {
                            for(int j= k-1; j> counter; j--)    {
                                values[j]= values[j-1];
                            }
                                values[counter]= a[i];  
                        }
                        if(counter< k) counter++;
                }
            return values;
        }
编辑:Joop Eggen为我解决了这个问题。向下滚动以查看答案。谢谢!

6 个答案:

答案 0 :(得分:4)

正如评论中已经指出的那样,只需返回已排序数组的一部分。

public static int[] nrSmallest(int[] a, int k)  {
    // check parameters..

    // copy all so we don't sort a
    int[] sorted = Arrays.copyOf(a, a.length);
    Arrays.sort(sorted);
    return Arrays.copyOf(sorted, Math.min(k, sorted.length));
}

答案 1 :(得分:3)

如果无法修改原始数组,通常使用某种类型的优先级队列来完成,通常是binary heap

您在示例中使用的方法是O(n ^ 2),并使用O(k)额外空间。对原始数组进行排序并选择前k项为O(n log n)。如果复制数组然后对其进行排序,则使用O(n)额外空间。

使用堆是O(n log k),并且需要O(k)额外空间。

有一个O(n)解决方案涉及操纵原始数组(或制作数组的副本并对其进行操作)。请参阅Quickselect

我自己的测试显示Quickselect在一般情况下更快,但是当要选择的项目数(k)小于总项目数(n)的1%时,堆选择更快。请参阅我的博客帖子When theory meets practice。例如,从200万个列表中选择前100个项目时,这非常方便。

答案 2 :(得分:1)

(已更正) 保留您的代码:

            for (int i= k; i < a.length; i++) {
                    if (a[i] < values[counter]) { // Found small value
                        // Insert sorted
                        for (int j = k-1; j >= 0; j--) {
                            if (j == 0 || a[i] > values[j-1]) { // Insert pos
                                // Move greater ones up.
                                for (int m = k - 1; m > j; m--) {
                                    values[m] = values[m - 1];
                                }
                                values[j] = a[i]; // Store
                                break; // Done
                            }
                        }
                    }
            }

答案 3 :(得分:0)

int [] values = Arrays.copyOf(a,k);这条线是错的。你只复制k个元素。但是你应该复制所有元素,然后对数组进行排序。

答案 4 :(得分:0)

首先对数组进行排序,然后将数组的已排序部分返回到k。

public static int[] nrSmallest(int[] a, int k)  {
        if(k <1 || k>a.length)
            throw new IllegalArgumentException("must be at least 1");
        Arrays.sort(a);        
        return Arrays.copyOf(a,k);
    }

答案 5 :(得分:0)

你可以使用quicksort的“旋转”思想, 数据透视表示数组中该数字的“等级”,因此您的最终目标是在索引“k”处有一个数据透视图,这将导致子数组小于第K个元素,换句话说,前K个最小数字(不是完全排序)。