1. 程式人生 > >bfprt演算法----找出陣列中最小的k個數(Java)

bfprt演算法----找出陣列中最小的k個數(Java)



無序陣列中最小的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;
    }