最小的K个数

题目

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

解题

方法一:快排思想
找到排列后的第k个数的id就好了

import java.util.ArrayList;
import java.util.TreeSet;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if(input == null || k<=0 || k>input.length)
            return result;
        int left = 0;
        int right = input.length - 1;
        int id = partition(input,left,right);
        k = k - 1;// 下标转化为0 开始
        while(id !=k){
             if(id>k){
                 right = id - 1;
                 id = partition(input,left,right);
             }else{
                 left = id + 1;
                 id = partition(input,left,right);
             }
         }
        for(int i=0;i<=id;i++){
            result.add(input[i]);
        }
        return result;
    }
    // 划分位置
    public int partition(int [] A,int low ,int high){
        int x = A[high];
        int i = low - 1;// i 记录较大数id j 较小数id
        for( int j = low;j<= high - 1;j++){
            if( A[j] <= x){
                i = i + 1;
                swap(A,i,j);
            }
        }
        i = i + 1;
        swap(A,i,high);
        return i;
    }
    public void swap(int[] input,int i,int j){
        int tmp = input[i];
        input[i] = input[j];
        input[j] = tmp;
    }
}

下面快排的程序要好好理解
i:较大数的id
j:较小数的id
当A[j] <=x的时候,i j元素进行互换

    public int partition(int [] A,int low ,int high){
        int x = A[high];
        int i = low - 1;// i 记录较大数id j 较小数id
        for( int j = low;j<= high - 1;j++){
            if( A[j] <= x){
                i = i + 1;
                swap(A,i,j);
            }
        }
        i = i + 1;
        swap(A,i,high);
        return i;
    }

Partition函数也可以这样写
两个指针两侧找,左侧找到较大数,右侧找到较小数,互换,两指针相遇时候结束

    public int Paratition(int[] A,int left ,int right){
        if(left> right)
            return -1;
        int i = left;
        int j = right;
        int mid = A[left];
        if(i<j){
            while(i<j){

                while(i<j && mid< A[j])
                    j--;
                if(i<j){
                    A[i] = A[j];
                    i++;
                }
                while(i<j && A[i]< mid)
                    i++;
                if(i<j){
                    A[j] = A[i];
                    j--;
                }
            }
            A[i] = mid;
        }
        return i;

    }

方法二:大顶堆
题目要求找到最小的k个数,建立k个元素的大顶堆
先将堆中添加k个元素,并调整为大顶堆
剩余的元素,每次加入一个元素,当这个元素比堆顶的元素还要大,不加入到堆中
当这个元素比堆顶元素小,用这个元素替换堆顶元素,并调整为大顶堆
最后堆内的k个元素就是最小的k个元素
这个思想适合在大量数据中找到最小的k个数
时间复杂度 O(nlogk)

你可能感兴趣的:(剑指offer)