寻找数组中最小的 K 个元素

huangapple go评论73阅读模式
英文:

Find K Smallest Elements in an Array

问题

我想在数组中找到最小的 K 个元素,我已经基本上将数组排序成了一个最小堆结构,但输出结果仍然是错误的。

这是我的输入:

arr = [9,4,7,1,-2,6,5]
k = 3

这是代码部分:

public static int[] findKSmallest(int[] arr, int k) {
    int[] result = new int[k];
    int heapSize = arr.length;
    // 写入 - 你的 - 代码部分  

    for (int i = (heapSize - 1) / 2; i >= 0; i--) {
        minHeap(arr, i, heapSize);
    }

    for (int j = 0; j < k; j++) {
        result[j] = arr[j];
    }
    return result;
}
public static void minHeap(int[] arr, int index, int heapSize) {
    int smallest = index;
    while (smallest < heapSize / 2) {
        int left = (2 * index) + 1; // 比索引大 1
        int right = (2 * index) + 2; // 比索引大 2 

        if (left < heapSize && arr[left] < arr[index]) {
            smallest = left;
        }

        if (right < heapSize && arr[right] < arr[smallest]) {
            smallest = right;
        }

        if (smallest != index) {
            int temp = arr[index];
            arr[index] = arr[smallest];
            arr[smallest] = temp;
            index = smallest;
        } else {
            break;
        }
    }
}

这是我期望的输出:

[-2,1,4]

尽管我的输出是:

[-2,1,5]

请问我哪里出错了。

英文:

I want to find the K smallest elements in an array, and I was able to basically sort my array into a min-heap structure but I am still getting the wrong output.

Here are my inputs:

arr = [9,4,7,1,-2,6,5]
k = 3

Here's the Code:

public static int[] findKSmallest(int[] arr, int k) {
    int[] result = new int[k];
    int heapSize = arr.length;
    // Write - Your - Code  

    for (int i = (heapSize - 1) / 2; i &gt;= 0; i--) {
        minHeap(arr, i, heapSize);
    }

    for (int j = 0; j &lt; k; j++) {
        result[j] = arr[j];
    }
    return result;
}
public static void minHeap(int[] arr, int index, int heapSize) {
    int smallest = index;
    while (smallest &lt; heapSize / 2) {
        int left = (2 * index) + 1; // 1 more than half the index
        int right = (2 * index) + 2; // 2 more than half the index 

        if (left &lt; heapSize &amp;&amp; arr[left] &lt; arr[index]) {
            smallest = left;
        }

        if (right &lt; heapSize &amp;&amp; arr[right] &lt; arr[smallest]) {
            smallest = right;
        }

        if (smallest != index) {
            int temp = arr[index];
            arr[index] = arr[smallest];
            arr[smallest] = temp;
            index = smallest;
        } else {
            break;
        }
    }
}

Here is my expected output:

[-2,1,4]

Though my output is:

[-2,1,5]

Please I would like to know where I went wrong.

答案1

得分: 1

构建小顶堆后,您需要提取元素并适当调整树结构。您之前通过索引从数组中获取元素,但这不是堆的工作方式。

我稍微修改了您的 minHeap() 方法,使用了 递归,您应该检查 arr[smallest] < arr[left] 而不是相反的情况。

public static int[] findKSmallest(int[] arr, int k) {
    int[] result = new int[k];
    int heapSize = arr.length;
    // 写 - 你的 - 代码

    for (int i = (heapSize - 1) / 2; i >= 0; i--) {
        minHeap(arr, heapSize, i);
    }

    // 从堆中提取元素
    for (int i = heapSize - 1; i > 0; i--) {
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        minHeap(arr, 0, i);
    }

    for (int j = 0; j < k; j++) {
        result[j] = arr[j];
    }
    return result;
}
public static void minHeap(int[] arr, int index, int heapSize) {
    int smallest = index;
    int left = (2 * index) + 1; // 比索引大1
    int right = (2 * index) + 2; // 比索引大2
    if (left < heapSize && arr[smallest] < arr[left]) {
        smallest = left;
    }
    if (right < heapSize && arr[smallest] < arr[right]) {
        smallest = right;
    }
    if (smallest != index) {
        int temp = arr[index];
        arr[index] = arr[smallest];
        arr[smallest] = temp;
        minHeap(arr, smallest, heapSize);
    }
}

希望这有所帮助。如预期的结果是:

[-2, 1, 4]
英文:

After you build your minHeap you have to extract element and appropriately adjust tree. You simply took elements from array by index, which is not how heap works.

I slightly modified your minHeap() method to use recursion and you should check arr[smallest] &lt; arr[left] not the orther way around.

public static int[] findKSmallest(int[] arr, int k) {
    int[] result = new int[k];
    int heapSize = arr.length;
    // Write - Your - Code

    for (int i = (heapSize - 1) / 2; i &gt;= 0; i--) {
        minHeap(arr, heapSize, i);
    }

    // extract elements from heap
    for (int i = heapSize - 1; i &gt; 0; i--) {
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        minHeap(arr, 0, i);
    }

    for (int j = 0; j &lt; k; j++) {
        result[j] = arr[j];
    }
    return result;
}
public static void minHeap(int[] arr, int index, int heapSize) {
    int smallest = index;
    int left = (2 * index) + 1; // 1 more than half the index
    int right = (2 * index) + 2; // 2 more than half the index
    if (left &lt; heapSize &amp;&amp; arr[smallest] &lt; arr[left]) {
        smallest = left;
    }
    if (right &lt; heapSize &amp;&amp; arr[smallest] &lt; arr[right]) {
        smallest = right;
    }
    if (smallest != index) {
        int temp = arr[index];
        arr[index] = arr[smallest];
        arr[smallest] = temp;
        minHeap(arr, smallest, heapSize);
    }
}

Hope this helps. As expected the result is:

[-2, 1, 4]

答案2

得分: 0

自从Java 8以来,我们可以对流进行排序

替代代码:

Arrays.stream(arr).sorted().boxed().collect(Collectors.toList()).subList(0, k);

其中:

int[] arr = {9, 4, 7, 1, -2, 6, 5};
int k = 3; // toIndex

上下文中的替代代码和测试代码:

public static void main(String[] args) {
    int[] arr = {9, 4, 7, 1, -2, 6, 5};
    int k = 3; // toIndex

    List<Integer> listResult = Arrays.stream(arr)
            .sorted().boxed().collect(Collectors.toList()).subList(0, k);
    // 打印列表结果
    System.out.println("列表结果输出: " + listResult);

    int[] arrayResult = listResult.stream().mapToInt(i -> i).toArray();
    // 打印数组结果
    List<String> arrayResultAsString = Arrays.stream(arrayResult)
            .boxed().map(i -> String.valueOf(i)).collect(Collectors.toList());
    System.out.println("数组结果输出: " + arrayResultAsString);
}

输出结果:

列表结果输出: [-2, 1, 4]
数组结果输出: [-2, 1, 4]
英文:

Since Java 8 we can do Sorting stream

Alternative code:

Arrays.stream(arr).sorted().boxed().collect(Collectors.toList()).subList(0, k);

where:

int[] arr = {9,4,7,1,-2,6,5};
int k = 3; // toIndex

Alternative code in context and testbench:

public static void main(String[] args) {
    int[] arr = {9, 4, 7, 1, -2, 6, 5};
    int k = 3; // toIndex

    List&lt;Integer&gt; listResult = Arrays.stream(arr)
            .sorted().boxed().collect(Collectors.toList()).subList(0, k);
    // print out list result
    System.out.println(&quot;Output of list result: &quot; + listResult);


    int[] arrayResult = listResult.stream().mapToInt(i -&gt; i).toArray();
    // print out array result
    List&lt;String&gt; arrayResultAsString = Arrays.stream(arrayResult)
            .boxed().map(i -&gt; String.valueOf(i)).collect(Collectors.toList());
    System.out.println(&quot;Output of array result: &quot; + arrayResultAsString);
}

Output:

Output of list result: [-2, 1, 4]
Output of array result: [-2, 1, 4]

答案3

得分: 0

你可以使用 Arrays.stream​(int[]) 方法:

int[] arr = {9, 4, 7, 1, -2, 6, 5};
int k = 3;

int[] minHeap = Arrays.stream(arr).sorted().limit(k).toArray();

System.out.println(Arrays.toString(minHeap)); // [-2, 1, 4]
英文:

You can use Arrays.stream​(int[]) method:

int[] arr = {9, 4, 7, 1, -2, 6, 5};
int k = 3;

int[] minHeap = Arrays.stream(arr).sorted().limit(k).toArray();

System.out.println(Arrays.toString(minHeap)); // [-2, 1, 4]

答案4

得分: 0

如果K相对于数组大小较小,我的建议是使用选择排序,这可能是一个策略设计模式 - 具体取决于K与数组大小的关系,例如可以使用两种程序:对于较小的K,使用选择排序,对于较大的K,使用快速排序。而不是使用设计模式,使用简单的if语句可能也是一个不错的选择,例如选择<=30%<quick。

英文:

If K is relatively small to the array size my recommendation is to use selection sort, so it may be a design pattern Strategy - depending on K to array size relation with for example two procedures: selection sort for small K and quicksort for huge K. Instead of playing with design patterns good may be also simple if statement e.g. selection<=30%<quick

huangapple
  • 本文由 发表于 2020年9月27日 12:11:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/64084720.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定