【剑指offer】最小的K个数

一、题目描述

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

二、思路分析及代码实现

方法一:先排序后取值

直接调用Arrays的排序算法sort,默认升序,然后选择前k个放入list中即可
时间:16ms
内存:9508k

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<>();
      int len=input.length;
      if(len<k)
        return list;
      Arrays.sort(input);
      for(int i=0;i<k;i++){
        list.add(input[i]);
      }
      return list;
    }
}

方法二:使用冒泡排序挑选出小的K个数

因为冒泡排序每次都是挑选出数组中最大或最小的数,因此我们借助这个思想不将所有数组进行排序

public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
      ArrayList<Integer> list=new ArrayList<>();
      int len=input.length;
      if(len<k)
        return list;
      for(int i=0;i<k;i++){
        for(int j=0;j<len-i-1;j++){
          if(input[j+1]>input[j]){
            int temp=input[j];
            input[j]=input[j+1];
            input[j+1]=temp;
          }
        }
        list.add(input[len-1-i]);
      }
      return list;
    }

方法三:基于快速排序的partition函数

我们基于快速排序的partition函数,可以返回一个index值,这个K的左侧均小于它,右侧均大于它。
然后调用partition函数,判断返回的index和K值得大小判断我们所求得值在左侧还是右侧还是已经找到了

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
      int len=input.length;
      ArrayList<Integer> list=new ArrayList<>();
      if(len<k)
        return list;
      int low=0, high=len-1;
      while(low<=high){
        int index=partition(input,low,high);
        if(index==k-1){
          //我们找到的左侧为所需要的数
          break;
        }else if(index<k-1){
          //说明要找的在右侧部分
          low=index+1;
        }else{
          high=index-1;
        }
      }
      for(int i=0;i<k;i++){
        list.add(input[i]);
      }
      return list;
    }
  private int partition(int[] arr, int start, int end){
    int pivot=arr[end];
    int smaller=start-1;
    while(start<end){
      if(arr[start]<pivot){
        swap(arr,start++,++smaller);
      }else{
        start++;
      }
    }
    swap(arr,end,++smaller);
    return smaller;
  }
  private void swap(int[] arr, int a, int b){
    int temp=arr[a];
    arr[a]=arr[b];
    arr[b]=temp;
  }
}

存在的问题,会修改数组中的数据。
方法四:基于大顶堆

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        while(input == null || k <= 0 || k > input.length)
            return list ;
        int[] arr = new int[k];  //用于放最小的k个数
        for(int i=0;i<k;i++)
            arr[i] = input[i];//先放入前k个数
        for(int i = k/2-1; i >= 0; i--){
            adjustHeap(arr,i,k-1);//将数组调整成最大堆形式
        }
        for(int i = k;i < input.length; i++){
            if(input[i]<arr[0]){ //存在更小的数字时
                arr[0]=input[i];
                adjustHeap(arr,0,k-1);//重新调整最大堆
            }
        }
        for (int i = 0; i < arr.length; i++) {
            list.add(arr[i]);
        }
        return list ;
    }
    //给一个数组,以及该数组的某个范围,将该范围构造成堆,start为最小值
     private void adjustHeap(int[] arr,int start,int end){
        int temp = arr[start];
        int child = start*2+1;
        while(child <= end){
            if(child + 1 <= end && arr[child+1] > arr[child])
                child++;
            if(arr[child] < temp)
                break;
            arr[start] = arr[child];
            start = child;
            child = child*2+1;
        }
        arr[start] = temp;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值