bfprt算法----找出数组中最小的k个数(Java)

本文介绍了三种方法来找出无序数组中最小的k个数:1) 利用堆排序,时间复杂度O(Nlogk);2) 利用快速排序,平均时间复杂度O(n),最坏情况下O(n^2);3) 使用bfprt算法,时间复杂度O(n)。分别给出了Java实现代码。
摘要由CSDN通过智能技术生成


无序数组中最小的k个数

对于一个无序数组,数组中元素为互不相同的整数,请返回其中最小的k个数。

给定一个整数数组A及它的大小n,同时给定k,请返回其中最小的k个数。

测试样例:
[1,2,4,3],4,2
返回:[1,2]

(1)利用堆,时间复杂度O(Nlogk)

public class Main {
 public static void main(String[] args) {
  Main test = new Main();
  int[] a={3188,4522,2526,4085,1621,723,1073};
  int[] b=new int[6];
     b=test.findKthNumbers(a,7,6);
     System.out.println(b[0]);
     System.out.println(b[1]);
     System.out.println(b[2]);
     System.out.println(b[3]);
     System.out.println(b[4]);
     System.out.println(b[5]);
 }
 public int[] findKthNumbers(int[] A, int n, int k) {
        if(A==null||n<=k||k<1){
            return A;
        }
        int[] result=new int[k];
        heapSort(A,result,k);
        for(int i=k;i<n;i++){
            if(A[i]<result[0]){
                heapModify(result,A[i]);
            }
        }
        return result;
    }
    public void heapSort(int[] arr,int[] result,int k){
        result[0]=arr[0];
        for(int i=0;i<k;i++){
            result[i]=arr[i];
            int index=i;
            int parent=(i-1)/2;
            while(parent>=0&&result[parent]<result[index]){
                swap(result,parent,index);
                index=parent;
                parent=(parent-1)/2;
            }
        }
    }
    public void heapModify(int[] arr,int key){
        arr[0]=key;
        int k=arr.length;
        int index=0;
        int child=(index+1)*2-1;
        if(child+1<k){
            child=arr[child]>=arr[child+1]?child:child+1;
        } 
        while(child<k&&arr[index]<arr[child]){
            swap(arr,index,child);
            index=child;
            child=(child+1)*2-1;
         if(child+1<k){
          child=arr[child]>=arr[child+1]?child:child+1;
         }
        }
    }
    public void swap(int[] arr,int i,int j){
        int temp;
        temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }
}

(2) 利用快排  平均O(n) 最坏O(n^2)

public class Main {
  public static void main(String[] args) {
   Main test = new Main();
     int[] a={3188,4522,2526,4085,1621,723,1073};
     int[] b=new int[6];
        b=test.findKthNumbers(a,7,6);
        System.out.println(b[0]);
        System.out.println(b[1]);
        System.out.println(b[2]);
        System.out.println(b[3]);
        System.out.println(b[4]);
        System.out.println(b[5]);
 
    }

 
  public int[] findKthNumbers(int[] input, int n, int k) {
         if(input==null||n<=k||k<1){
             return input;
         }
         int[] result=new int[k];
  int start=0,end=input.length-1,key,i,j;
        while(end!=k-1){
            key=input[start];
            i=start;
            j=end;
            while(i<j){
                while(i<j&&input[j]>=key){
                    j--;
                }
                input[i]=input[j];
                while(i<j&&input[i]<=key){
                    i++;
                }
                input[j]=input[i];
            }
            input[i]=key;
            if(i==k-1) break;
            if(i>k-1)end=i-1;
            else start=i+1;
        }
        for(i=0;i<k;i++){
             result[i]=input[i];
        }
        return result;
    }

}

(3)bfprt  时间复杂度O(n)

public class Main {
 public static void main(String[] args) {
  Main test = new Main();
  int[] a={3188,4522,2526,4085,1621,723,1073};
  int[] b=new int[6];
     b=test.findKthNumbers(a,7,6);
     System.out.println(b[0]);
     System.out.println(b[1]);
     System.out.println(b[2]);
     System.out.println(b[3]);
     System.out.println(b[4]);
     System.out.println(b[5]);
 }
    public int[] findKthNumbers(int[] A, int n, int k) {
        if(A==null||n<=k||k<1){
            return A;
        }
        int[] result=new int[k];
        int key;
        int j=0;
        key=findK(A,0,n-1,k);//找到第k小数的值;
        for(int i=0;i<n;i++){
            if(A[i]<key){
             result[j++]=A[i];
            }
        }
        while(j!=k){
         result[j++]=key;
        }
        return result;
    }
    public int findK(int[] arr,int start,int end,int k){
        int key;
        int[] index=new int[2];
        key=selectKey(arr,start,end);//找中位数。
        index=quickSort(arr,start,end,key);//以中位数为基准,快速排序。
        if(index[0]<=k-1&&k-1<=index[1]){
            return arr[index[0]];
        }
        else if(index[0]>k-1){
            return findK(arr,0,index[0],k);
        }
        else{
            return findK(arr,index[1]+1,end,k);
        }
    }

//使用bfprt算法寻找中位数
    public int selectKey(int[] arr,int start,int end){
        if(end-start<=4){
            return midKey(arr,start,end);
        }
        int[] temp=new int[(end-start)/5+1];
        int j=0;
        for(int i=start;i<=end;i+=5){
            temp[j++]=midKey(arr,i,Math.min(end,i+4));
        }
        return selectKey(temp,0,(end-start)/5);
    }

//按中位数值快速排序
    public int[] quickSort(int[] arr,int start,int end,int key){
     int[] index=new int[2];
        if(start==end){
         index[0]=index[1]=start;
            return index;
        }
        int cur=start;
        int left=start;
        int right=end;
        while(cur<=right){
            if(arr[cur]>key){
             swap(arr,cur,right--);
            }
            else if(arr[cur]<key){
             swap(arr,cur++,left++);
            }
            else{
             cur++;
            }
        }
        index[0]=left;
        index[1]=right;
        return index;
    }

//对没五个的小组进行插入排序并返回小组中位数。
    public int midKey(int[] arr,int start,int end){
        if(start==end){
            return arr[start];
        }
        int mid=(start+end)/2;
        for(int i=start+1;i<=end;i++){
            int key=arr[i];
            int j=i-1;
            while(j>=start&&key<arr[j]){
                arr[j+1]=arr[j--];
            }
            arr[++j]=key;
        }
        return arr[mid];
    }
    public void swap(int[] arr,int i,int j){
        int temp;
        temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }


无序数组中最小的k个数

对于一个无序数组,数组中元素为互不相同的整数,请返回其中最小的k个数,顺序与原数组中元素顺序一致。

给定一个整数数组A及它的大小n,同时给定k,请返回其中最小的k个数。

测试样例:
[1,2,4,3],4,2
返回:[1,2]

(1)堆实现:

public int[] findKthNumbers(int[] A, int n, int k) {
         if(A==null||n<=k||k<1){
             return A;
         }
         int[] result=new int[k];
         heapSort(A,result,k);
         for(int i=k;i<n;i++){
             if(A[i]<result[0]){
                 heapModify(result,A[i]);
             }
         }
         int j=0;
         int count=0;
         int key=result[0];
         for(int i=0;i<n;i++){
             if(A[i]<key){
              count++;
             }
         }
         int c=k-count;
         for(int i=0;i<n;i++){
             if(A[i]<key){
              result[j++]=A[i];
             }
             if(A[i]==key&&c-->0){
                 result[j++]=A[i];
                }
         }
         return result;
     }
     public void heapSort(int[] arr,int[] result,int k){
         result[0]=arr[0];
         for(int i=0;i<k;i++){
             result[i]=arr[i];
             int index=i;
             int parent=(i-1)/2;
             while(parent>=0&&result[parent]<result[index]){
                 swap(result,parent,index);
                 index=parent;
                 parent=(parent-1)/2;
             }
         }
     }
     public void heapModify(int[] arr,int key){
         arr[0]=key;
         int k=arr.length;
         int index=0;
         int child=(index+1)*2-1;
         if(child+1<k){
             child=arr[child]>=arr[child+1]?child:child+1;
         } 
         while(child<k&&arr[index]<arr[child]){
             swap(arr,index,child);
             index=child;
             child=(child+1)*2-1;
          if(child+1<k){
           child=arr[child]>=arr[child+1]?child:child+1;
          }
         }
     }
     public void swap(int[] arr,int i,int j){
         int temp;
         temp=arr[i];
         arr[i]=arr[j];
         arr[j]=temp;
     }

(2)bfprt 

public int[] findKthNumbers(int[] A, int n, int k) {
        if(A==null||n<=k||k<1){
            return A;
        }
        int[] result=new int[k];
        int key;
        int j=0;
        int[] copyArr=new int[n];
        for (int i = 0; i < n; i++) {
      copyArr[i] = A[i];
     }
        key=findK(copyArr,0,n-1,k);//找到第k小数的值;
        int count=0;
        for(int i=0;i<n;i++){
            if(A[i]<key){
             count++;
            }
        }
        int c=k-count;
        for(int i=0;i<n;i++){
            if(A[i]<key){
             result[j++]=A[i];
            }
            if(A[i]==key&&c-->0){
                result[j++]=A[i];
               }
        }
        return result;
    }
    public int findK(int[] arr,int start,int end,int k){
        int key;
        int[] index=new int[2];
        key=selectKey(arr,start,end);//找中位数。
        index=quickSort(arr,start,end,key);//以中位数为基准,快速排序。
        if(index[0]<=k-1&&k-1<=index[1]){
            return arr[index[0]];
        }
        else if(index[0]>k-1){
            return findK(arr,0,index[0],k);
        }
        else{
            return findK(arr,index[1]+1,end,k);
        }
    }

//使用bfprt算法寻找中位数
    public int selectKey(int[] arr,int start,int end){
        if(end-start<=4){
            return midKey(arr,start,end);
        }
        int[] temp=new int[(end-start)/5+1];
        int j=0;
        for(int i=start;i<=end;i+=5){
            temp[j++]=midKey(arr,i,Math.min(end,i+4));
        }
        return selectKey(temp,0,(end-start)/5);
    }

//按中位数值快速排序
    public int[] quickSort(int[] arr,int start,int end,int key){
     int[] index=new int[2];
        if(start==end){
         index[0]=index[1]=start;
            return index;
        }
        int cur=start;
        int left=start;
        int right=end;
        while(cur<=right){
            if(arr[cur]>key){
             swap(arr,cur,right--);
            }
            else if(arr[cur]<key){
             swap(arr,cur++,left++);
            }
            else{
             cur++;
            }
        }
        index[0]=left;
        index[1]=right;
        return index;
    }

//对没五个的小组进行插入排序并返回小组中位数。
    public int midKey(int[] arr,int start,int end){
        if(start==end){
            return arr[start];
        }
        int mid=(start+end)/2;
        for(int i=start+1;i<=end;i++){
            int key=arr[i];
            int j=i-1;
            while(j>=start&&key<arr[j]){
                arr[j+1]=arr[j--];
            }
            arr[++j]=key;
        }
        return arr[mid];
    }
    public void swap(int[] arr,int i,int j){
        int temp;
        temp=arr[i];
        arr[i]=arr[j];
        arr[j]=temp;
    }





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值