最小的k个数-O(nlogk)解法

题目:给定一个无需的整型数组arr,找到其中最小的k个数


要求:时间复杂度为O(nlogk)


解题思路:

1.先建立一个含有k个数的大根堆,这个堆代表"目前选出的"k个最小的数,在堆里的k个元素中堆顶的元素是最小的k个数里最大的那个。

2.接下来遍历整个数,遍历的过程中看当前数是否比堆顶元素小。

3.如果当前遍历到的数比堆顶小,就把堆顶的元素替换成当前的数,然后从堆顶的位置调整整个堆,让替换操作后堆的最大元素继续处在堆顶的位置;

4.如果当前遍历到的数不比堆顶小,则不进行任何操作,继续遍历下一个数。

5.在遍历完成后,堆中的k个数就是所有数组中最小的k个数

代码如下:

public class TopK {
   
    public int[] getMinKNumsByHeap(int[] array, int k){
        if(k < 1 || k > array.length){
            return array;
        }

        int[] kHeap = new int[k];
        //选出k个数,建立大根堆,后续对这个大根堆进行维护
        for(int i = 0; i != k; i++){
            heapInsert(kHeap, array[i], i);
        }

        for(int i = k; i != array.length; i++){
            if(array[i] < kHeap[0]){
                kHeap[0] = array[i];
                heapify(kHeap, 0 , k);
            }
        }


        return kHeap;
    }

    //建堆
    public void heapInsert(int[] array, int value, int index){
        array[index] = value;
        while(index != 0){
            int parent = (index - 1) / 2;
            if(array[parent] < array[index]){
                //若比父位置大就交换
                swap(array, parent, index);

                //并来到父位置,再比较,直到不比父位置大,停住。
                index = parent;
            }else{
                break;
            }
        }
    }

    //调整堆  index位置的数变小了,往下沉 heapSize表示已经形成的堆的大小
    public void heapify(int[] array, int index, int heapSize){
        int left = index * 2 + 1;
        int right = index * 2 + 2;
        int largest = index;//largest记录左右两个孩子哪个比较大

        while(left < heapSize){
            if(array[left] > array[index]){
                largest = left;//左孩子大则largest记录左孩子的位置
            }
            if(right < heapSize && array[right] > array[largest]){
                largest = right;
            }
            if(largest != index){
                swap(array, largest, index);
            }else{
                //若largest == index则说明我和左右孩子之间的最大值是自己,不用往下沉
                break;
            }
            index = largest;
            left = index * 2 + 1;
            right = index * 2 + 2;
        }
    }

    public void swap(int[] array, int i, int j){
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

猜你喜欢

转载自blog.csdn.net/hoji_James/article/details/80600701