Java深入分析與解決Top-K問題
題目
求最小的K個(gè)數(shù)
設(shè)計(jì)一個(gè)算法,找出數(shù)組中最小的k個(gè)數(shù)。以任意順序返回這k個(gè)數(shù)均可。

解題方案
方法一
排序(冒泡/選擇)
思路
1,冒泡排序是每執(zhí)行一次,就會(huì)確定最終位置,執(zhí)行K次后,就可以得到結(jié)果,時(shí)間復(fù)雜度為O(n * k),當(dāng)k<<n時(shí),O(n * k)的性能會(huì)比O(N*logN)好。
2,選擇排序每執(zhí)行依次,就會(huì)通過確定一個(gè)最大的或最小的放在一端,通過選擇排序,執(zhí)行K次就可以得到最大的K個(gè)數(shù)了。時(shí)間復(fù)雜度時(shí)O(N * K)。
代碼實(shí)現(xiàn)
//冒泡排序
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把序列分為兩個(gè)部分,再將兩個(gè)部分進(jìn)行再次遞歸;
2,利用分治思想,即劃分操作partition,根據(jù)主元素pivot調(diào)整序列,比pivot大的放在左端,比pivot小的放在右端,這樣確定主元素pivot的位置pivotIndex,如果pivotIndex剛好是k-1,那么前k-1位置的數(shù)就是前k大的元素,即我們要求的top K。
時(shí)間復(fù)雜度: O(n)
代碼實(shí)現(xià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,構(gòu)建一個(gè)最大堆
2,遍歷原數(shù)組,元素入隊(duì),當(dāng)堆的大小為K時(shí),只需要將堆頂元素于下一個(gè)元素比較,如果大于堆頂元素,則將堆頂元素刪除,將該元素插入堆中,直到遍歷完所有元素
3,將queue存儲(chǔ)的K個(gè)數(shù)出隊(duì)
時(shí)間復(fù)雜度:為O(N*logK)
代碼實(shí)現(xiàn)
public class TopK {
public int[] smallestK(int[] arr, int k) {
int[] ret = new int[k];
if(k==0 || arr.length==0){
return ret;
}
// 1,構(gòu)建一個(gè)最大堆
// JDK的優(yōu)先級隊(duì)列是最小堆, 就要用到我們比較器
Queue<Integer> queue = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
//2,遍歷原數(shù)組,進(jìn)行入隊(duì)
for(int value:arr){
if(queue.size() < k){
queue.offer(value);
}else{
if(value < queue.peek()){
queue.poll();
queue.offer(value);
}
}
}
//3,將queue中存儲(chǔ)的K個(gè)元素出隊(duì)
for(int i = 0;i < k;i++){
ret[i] = queue.poll();
}
return ret;
}
}
到此這篇關(guān)于Java深入分析與解決Top-K問題的文章就介紹到這了,更多相關(guān)Java Top-K內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中Buffer緩沖區(qū)的ByteBuffer類詳解
這篇文章主要介紹了Java中Buffer緩沖區(qū)的ByteBuffer類詳解,ByteBuffer類是Java NIO庫中的一個(gè)重要類,用于處理字節(jié)數(shù)據(jù),它提供了一種靈活的方式來讀取、寫入和操作字節(jié)數(shù)據(jù),ByteBuffer類是一個(gè)抽象類,可以通過靜態(tài)方法創(chuàng)建不同類型的ByteBuffer對象,需要的朋友可以參考下2023-10-10
Java如何將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫
這篇文章主要為大家詳細(xì)介紹了Java將Excel數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
關(guān)于File與MultipartFile的用法概述
這篇文章主要介紹了關(guān)于File與MultipartFile的用法概述,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-09-09
關(guān)于Java中的繼承和組合的一個(gè)錯(cuò)誤使用的例子
這篇文章主要介紹了關(guān)于Java中的繼承和組合的一個(gè)錯(cuò)誤使用的例子,需要的朋友可以參考下2016-08-08
Java數(shù)據(jù)結(jié)構(gòu)之棧的詳解
這篇文章主要介紹了Java數(shù)據(jù)結(jié)構(gòu)之棧簡單操作的相關(guān)資料,需要的朋友可以參考下,希望能夠給你帶來幫助2021-09-09
Java設(shè)計(jì)模式之單態(tài)模式(Singleton模式)介紹
這篇文章主要介紹了Java設(shè)計(jì)模式之單態(tài)模式(Singleton模式)介紹,本文講解了如何使用單例模式、使用單例模式注意事項(xiàng)等內(nèi)容,需要的朋友可以參考下2015-03-03

