最小的K个数(数组)

来源:互联网 发布:鼠标自动点击软件 mac 编辑:程序博客网 时间:2024/06/15 00:42

题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4。

思路一:

import java.util.ArrayList;import java.util.Arrays;public class Solution {    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {        ArrayList<Integer> list = new ArrayList<>();        if (input.length <= 0 || k <= 0 || k > input.length) return list;        Arrays.sort(input);        for (int i = 0; i < k; i++)            list.add(input[i]);        return list;    }}

思路二:

快排,时间复杂度为O(NlogN)~O(N^2),空间复杂度为O(logN)~O(N)

import java.util.ArrayList;public class Solution {    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {        ArrayList<Integer> list = new ArrayList<>();        if (input.length <= 0 || k <= 0 || k > input.length) return list;        QuickSort(input, 0, input.length - 1);        for (int i = 0; i < k; i++)            list.add(input[i]);        return list;    }    private void QuickSort(int[] arr, int low, int high)    {        int index;        while (low < high)        {            index = partition(arr, low, high);            QuickSort(arr, low, index - 1);            low = index + 1; //优化1:避免了尾递归        }    }    private int partition(int[] arr, int low, int high)    {        int flag = arr[low];        while(low < high)        {            while (low < high && arr[high] >= flag)                high--;            arr[low] = arr[high];            while(low < high && arr[low] <= flag)                low++;            arr[high] = arr[low];        }        arr[low] = flag;        return low;    }}

思路三:

堆排序

构建一个大顶堆的时间复杂度为O(N),重建大顶堆的时间复杂度为O(NlogN),总时间复杂度为O(NlogN)

空间复杂度O(1)

import java.util.ArrayList;public class Solution {    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {        ArrayList<Integer> list = new ArrayList<>();        if (input.length <= 0 || k <= 0 || k > input.length) return list;        HeapSort(input);        for (int i = 0; i < k; i++)            list.add(input[i]);        return list;    }    private void HeapSort(int[] arr) // 从小到大排序,建立一个大顶堆;从大到小排序,建立一个小顶堆    {        for (int i = arr.length/2-1; i >=0; i--)  //非终端节点的范围0~length/2-1        {            HeapAdjust(arr, i, arr.length);        }        for (int i = arr.length - 1; i >= 0; i--)        {            swap(arr, 0, i);            HeapAdjust(arr, 0, i);        }    }    private void HeapAdjust (int[] arr, int s, int m)    {        int temp = arr[s];        int j = 2 * s + 1;        for (; j <= m - 1; j = 2 * j + 1)        {            if (j < m - 1 && arr[j] < arr[j + 1]) ++j;            if (temp >= arr[j]) break;            arr[s] = arr[j];            s = j;        }        arr[s] = temp;    }    private void swap(int[] arr, int i, int j)    {        int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }}

思路四:

改进的堆排序

对数组的前k个数建立一个大顶堆,将剩余N-K个数,依次与堆顶比较,若比堆顶小,则替换堆顶,再调整堆。最终将堆里的k个数加入列表中。

建立一个大顶堆的时间复杂度为O(k),调整大顶堆的时间复杂度为O((N-k)logk),总的时间复杂度为O(Nlogk)

空间复杂度为O(k+1)即O(k)

最后输出的k个数可以不按照从小到大输出

import java.util.ArrayList;public class Solution {    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {        ArrayList<Integer> list = new ArrayList<>();        if (input.length <= 0 || k <= 0 || k > input.length) return list;        HeapSort(input, k);        for (int i = 0; i < k; i++)            list.add(input[i]);        return list;    }    private void HeapSort(int[] arr, int k) // 从小到大排序,建立一个大顶堆;从大到小排序,建立一个小顶堆    {        int[] karr = new int[k];        for (int i = 0; i < k; i ++)            karr[i] = arr[i];        for (int i = k/2-1; i >=0; i--)  //非终端节点的范围0~length/2-1        {            HeapAdjust(karr, i, k);// // karr为大顶堆        }        for (int i = k; i < arr.length; i++)        {            if (arr[i] < karr[0])            {                karr[0] = arr[i];                HeapAdjust(karr, 0, k);            }        }        for (int i = 0; i < k; i++)            arr[i] = karr[i];    }    private void HeapAdjust (int[] arr, int s, int m)    {        int temp = arr[s];        int j = 2 * s + 1;        for (; j <= m - 1; j = 2 * j + 1)        {            if (j < m - 1 && arr[j] < arr[j + 1]) ++j;            if (temp >= arr[j]) break;            arr[s] = arr[j];            s = j;        }        arr[s] = temp;    }}


如果要求输出的k个数从小到大输出,在上述基础上加个循环

import java.util.ArrayList;public class Solution {    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {        ArrayList<Integer> list = new ArrayList<>();        if (input.length <= 0 || k <= 0 || k > input.length) return list;        HeapSort(input, k);        for (int i = 0; i < k; i++)            list.add(input[i]);        return list;    }    private void HeapSort(int[] arr, int k) // 从小到大排序,先建立一个大顶堆;从大到小排序,先建立一个小顶堆    {        int[] karr = new int[k];        for (int i = 0; i < k; i ++)            karr[i] = arr[i];        for (int i = k/2-1; i >=0; i--)  //非终端节点的范围0~length/2-1        {            HeapAdjust(karr, i, k);        }        for (int i = k; i < arr.length; i++)        {            if (arr[i] < karr[0])            {                karr[0] = arr[i];                HeapAdjust(karr, 0, k);            }        }        for (int i = k - 1; i >= 0; i--)//加循环        {            swap(karr, 0, i);            HeapAdjust(karr, 0, i);        }        for (int i = 0; i < k; i++)            arr[i] = karr[i];    }    private void HeapAdjust (int[] arr, int s, int m)    {        int temp = arr[s];        int j = 2 * s + 1;        for (; j <= m - 1; j = 2 * j + 1)        {            if (j < m - 1 && arr[j] < arr[j + 1]) ++j;            if (temp >= arr[j]) break;            arr[s] = arr[j];            s = j;        }        arr[s] = temp;    }    private void swap(int[] arr, int i, int j)    {        int temp = arr[i];        arr[i] = arr[j];        arr[j] = temp;    }}