首頁  >  文章  >  Java  >  如何使用Java解決Top-K問題

如何使用Java解決Top-K問題

PHPz
PHPz轉載
2023-04-22 15:04:081355瀏覽

題目

求最小的K個數

設計一個演算法,找出陣列中最小的k個數。以任意順序傳回這k個數均可。

如何使用Java解決Top-K問題

解題方案

方法一

#排序(冒泡/選擇)

想法

1,冒泡排序是每執行一次,就會確定最終位置,執行K次後,就可以得到結果,時間複雜度為O(n * k),當k2,選擇排序每執行依次,就會透過確定一個最大的或最小的放在一端,透過選擇排序,執行K次就可以得到最大的K個數了。時間複雜度時O(N * K)。

程式碼實作

  //冒泡排序
    public static int[] topKByBubble(int[] arr, int k) {
        int[] ret = new int[k];
        if (k == 0 || arr.length == 0) {
            return ret;
        }
        for (int i = 0; i < k; i++) {
            for (int j = arr.length - 1; j < i; j--) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr, j, j + 1);
                }
            }
            ret[i] = arr[i];
        }
        return ret;
    }
    //选择排序
    public static int[] topKBySelect(int[] arr, int k) {
        int[] ret = new int[k];
        for (int i = 0; i < k; i++) {
            int maxIndex = i;
            int maxNum = arr[maxIndex];
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] > maxNum) {
                    maxIndex = j;
                    maxNum = arr[j];
                }
            }
            if (maxIndex != i) {
                swap(arr, maxIndex, i);
            }
            ret[i] = arr[i];
        }
        return ret;
    }
    public static void swap(int[] arr, int a, int b) {
        int temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }

方法二

分治-快速排序

思路

1,快速排序的核心是分治思想,先透過分治partition把序列分成兩個部分,再將兩個部分進行再次遞歸;

2,利用分治思想,即劃分操作partition,根據主元素pivot調整序列,比pivot大的放在左端,比pivot小的放在右端,這樣確定主元素pivot的位置pivotIndex,如果pivotIndex剛好是k-1,那麼前k-1位置的數就是前k大的元素,即我們要求的top K。

時間複雜度: O(n)

程式碼實作

public static int[] topKByPartition(int[] arr, int k){
    if(arr.length == 0 || k <= 0){
        return new int[0];
    }
    return quickSort(arr,0,arr.length-1,k);

}
//快速排序
public static int[] quickSort(int[] arr, int low, int high, int k){
    int n = arr.length;
    int pivotIndex = partition(arr, low, high);
    if(pivotIndex == k-1){
        return Arrays.copyOfRange(arr,0,k);
    }else if(pivotIndex > k-1){
        return quickSort(arr,low,pivotIndex-1,k);
    }else {
        return quickSort(arr,pivotIndex+1,high,k);
    }
}
public static int partition(int[] arr, int low, int high){
   if(high - low == 0){
       return low;
   }
   int pivot = arr[high];
   int left = low;
   int right = high-1;
   while (left < right){
       while (left < right && arr[left] > pivot){
           left++;
       }
       while (left < right && arr[right] < pivot){
           right--;
       }
       if(left < right){
           swap(arr,left,right);
       }else {
           break;
       }
   }
   swap(arr,high,left);
   return left;
}
public static void swap(int[] arr,int a, int b){
    int temp = arr[a];
    arr[a] = arr[b];
    arr[b] = temp;
}

方法三######利用堆疊#####想法#### ##1,建立一個最大堆######2,遍歷原始數組,元素入隊,當堆的大小為K時,只需要將堆頂元素於下一個元素比較,如果大於堆頂元素,則將堆頂元素刪除,將該元素插入堆中,直到遍歷完所有元素######3,將queue儲存的K個數出隊######時間複雜度:為O(N *logK)######程式碼實作###
public class TopK {
    public int[] smallestK(int[] arr, int k) {
        int[] ret = new int[k];
        if(k==0 || arr.length==0){
            return ret;
        }
        // 1,构建一个最大堆
        // JDK的优先级队列是最小堆, 就要用到我们比较器
        Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        //2,遍历原数组,进行入队
        for(int value:arr){
            if(queue.size() < k){
                queue.offer(value);
            }else{
                if(value < queue.peek()){
                    queue.poll();
                    queue.offer(value);
                }
            }
        }
        //3,将queue中存储的K个元素出队
        for(int i = 0;i < k;i++){
            ret[i] = queue.poll();
        }
        return ret;
    }
}

以上是如何使用Java解決Top-K問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除