Top k問題的討論(三種java實現)
在很多的筆試和麵試中,喜歡考察Top K.下面從自身的經驗給出三種實現方式及實用範圍。
合併法
這種方法適用於幾個陣列有序的情況,來求Top k。時間複雜度為O(k*m)。(m:為陣列的個數).具體實現如下:
/**
* 已知幾個遞減有序的m個數組,求這幾個資料前k大的數
*適合採用Merge的方法,時間複雜度(O(k*m);
*/
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
public class TopKByMerge{
public int[] getTopK(List<List<Integer>>input,int k){
int index[]=new int[input.size()];//儲存每個陣列下標掃描的位置;
int result[]=new int[k];
for(int i=0;i<k;i++){
int max=Integer.MIN_VALUE;
int maxIndex=0;
for(int j=0;j<input.size();j++){
if(index[j]<input.get(j).size()){
if(max<input.get(j).get(index[j])){
max=input.get(j).get(index[j]);
maxIndex=j;
}
}
}
if (max==Integer.MIN_VALUE){
return result;
}
result[i]=max;
index[maxIndex]+=1;
}
return result;
}
快排過程法
快排過程法利用快速排序的過程來求Top k.平均時間複雜度為(O(k*logn).適用於無序單個數組。具體Java實現如下:
/*
*利用快速排序的過程來求最小的k個數
*
*/
public class TopK{
int partion(int a[],int first,int end){
int i=first;
int main=a[end];
for(int j=first;j<end;j++){
if(a[j]<main){
int temp=a[j];
a[j]=a[i];
a[i]=temp;
i++;
}
}
a[end]=a[i];
a[i]=main;
return i;
}
void getTopKMinBySort(int a[],int first,int end,int k){
if(first<end){
int partionIndex=partion(a,first,end);
if(partionIndex==k-1)return;
else if(partionIndex>k-1)getTopKMinBySort(a,first,partionIndex-1,k);
else getTopKMinBySort(a,partionIndex+1,end,k);
}
}
public static void main(String []args){
int a[]={2,20,3,7,9,1,17,18,0,4};
int k=6;
new TopK().getTopKMinBySort(a,0,a.length-1,k);
for(int i=0;i<k;i++){
System.out.print(a[i]+" ");
}
}
}
採用小根堆或者大根堆
求最大K個採用小根堆,而求最小K個採用大根堆。
求最大K個的步奏:
1、根據資料前K個建立K個節點的小根堆。
2、在後面的N-K的資料的掃描中,
如果資料大於小根堆的根節點,則根節點的值覆為該資料,並調節節點至小根堆。
如果資料小於或等於小根堆的根節點,小根堆無變化。
求最小K個跟這求最大K個類似。時間複雜度O(nlogK)(n:資料的長度),特別適用於大資料的求Top K。
/**
* 求前面的最大K個 解決方案:小根堆 (資料量比較大(特別是大到記憶體不可以容納)時,偏向於採用堆)
*
*
*/
public class TopK {
/**
* 建立k個節點的小根堆
*
* @param a
* @param k
* @return
*/
int[] createHeap(int a[], int k) {
int[] result = new int[k];
for (int i = 0; i < k; i++) {
result[i] = a[i];
}
for (int i = 1; i < k; i++) {
int child = i;
int parent = (i - 1) / 2;
int temp = a[i];
while (parent >= 0 &&child!=0&& result[parent] >temp) {
result[child] = result[parent];
child = parent;
parent = (parent - 1) / 2;
}
result[child] = temp;
}
return result;
}
void insert(int a[], int value) {
a[0]=value;
int parent=0;
while(parent<a.length){
int lchild=2*parent+1;
int rchild=2*parent+2;
int minIndex=parent;
if(lchild<a.length&&a[parent]>a[lchild]){
minIndex=lchild;
}
if(rchild<a.length&&a[minIndex]>a[rchild]){
minIndex=rchild;
}
if(minIndex==parent){
break;
}else{
int temp=a[parent];
a[parent]=a[minIndex];
a[minIndex]=temp;
parent=minIndex;
}
}
}
int[] getTopKByHeap(int input[], int k) {
int heap[] = this.createHeap(input, k);
for(int i=k;i<input.length;i++){
if(input[i]>heap[0]){
this.insert(heap, input[i]);
}
}
return heap;
}
public static void main(String[] args) {
int a[] = { 4, 3, 5, 1, 2,8,9,10};
int result[] = new TopK().getTopKByHeap(a, 3);
for (int temp : result) {
System.out.println(temp);
}
}
}
相關推薦
Top k問題的討論(三種java實現)
在很多的筆試和麵試中,喜歡考察Top K.下面從自身的經驗給出三種實現方式及實用範圍。 合併法 這種方法適用於幾個陣列有序的情況,來求Top k。時間複雜度為O(k*m)。(m:為陣列的個數).具體實現如下: /** * 已知幾個遞減有序的m個數組
刪除鏈表的倒數第N個節點(三種方法實現)
from ++ n+1 while end != bsp -- 結點 刪除鏈表的倒數第N個節點 給定一個鏈表,刪除鏈表的倒數第 n 個節點,並且返回鏈表的頭結點。 示例: 給定一個鏈表: 1->2->3->4->5, 和 n = 2. 當刪
最短路和差分約束(三種演算法實現)( Til the Cows Come Home )
題目訓練連結(密碼hpuacm): https://vjudge.net/contest/246705 我會分別用 迪傑斯特拉 優先佇列和鏈式前向星優化過的迪傑斯特拉 SPFA演算法 三種方法講一下例題。 此外上述三種演算法是求單源最短路問題, 這裡還會
url地址資料引數轉化JSON物件(js三種方法實現)
當我們用get方法提交表單時,在url上會顯示出請求的引數組成的字串,例如:http://localhost:3000/index.html?phone=12345678901&pwd=123123,在伺服器端我們要獲取其中的引數來進行操作,這種情況下,就要對請求過來的網址進行拆解了。下面將用3種方法
【轉】Mybatis傳多個參數(三種解決方案)
三種 方案 var nbsp myba rom name bsp 什麽 轉自: http://www.2cto.com/database/201409/338155.html 據我目前接觸到的傳多個參數的方案有三種。 第一種方案: DAO層的函數方法 Public
數據結構-冒泡排序(Python&java實現)
冒泡排序1. 冒泡算法的核心思想冒泡排序的核心思想就是掃描數據清單,找到亂序的兩個相鄰的數據進行兩兩比較並交換位置,然後繼續掃描數據,接著反復重復上述的操作直至排序結束。2. 示例我們以23,15,58,-4,99,0這組無序的數字為例:例子為從小到大排序,初始狀態:23,15,58, -4,99
數據結構-插入排序(Python&java實現)
數據結構 java python 插入排序1.插入排序的工作原理插入排序的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。2.示例我們以3,0,89,67,-2,9這組無序的數字為例:例子為從小到大排序,初始狀態 3 0 89 67 -2 9
修改陣列中的變數,無法立馬觸發檢視更新(三種解決方案)
第一:使用$set. 直接給student賦值操作,雖然可以新增屬性,但是不會觸發檢視更新 mounted () { this.student.age = 24}原因是:受 ES5 的限制,Vue.js 不能檢測到物件屬性的新增或刪除。因為 Vue.js 在初始化例項時將屬性轉為 getter/sette
使用結巴分詞(jieba)對自然語言進行特徵預處理(Python、Java 實現)
一、前言 之前使用基於 Python 語言的 Spark 進行機器學習,程式設計起來是十分簡單。 ① 但是演算法部署到雲伺服器上,是一個障礙。 ② 得藉助 Flask/Django 等 Python W
Winform遍歷視窗的所有控制元件(幾種方式實現)
C#遍歷窗體所有控制元件或某型別所有控制元件 //遍歷窗體所有控制元件, foreach (Control control in this.Controls) { //遍歷後的操作... control.Enabled = false; } 遍歷某個panel的所有控制元件
js對url進行編碼和解碼(三種方式區別)
*** 只有 0-9[a-Z] $ - _ . + ! * ' ( ) , 以及某些保留字,才能不經過編碼直接用於 URL。 ***例如:搜尋的中文關鍵字,複製網址之後再貼上就會發現該URL已經被轉碼。 1、escape 和 unescape 原理:對除ASCII字母、數字、標點符號 @ * _ +
2.二維陣列中的查詢(python和java實現)
題目:在一個二維陣列中,每一行都是按照從左到右遞增的順序排序,每一列都是安裝從上到下遞增的順序排序。請完成一個函式,輸入這樣的一個二維陣列和一個整數,判斷陣列中書否含有該整數。 演算法思想:我們知道每一行都是遞增排序的,每一列也是從上到下遞增排序的,所以左上角的數是最小的,
python 實現 列表 選擇排序 演算法(兩種方法實現)
方法一:(remove方法) arr = [2, 3, 5, 6, 4, 1, 9] #找出最小元素 def findsmallest(arr): smallest = arr[0] #假設第一個元素為最小值 for i in range(1,len(arr)):
Mybatis傳多個參數(三種解決方案) mapper.xml的sql語句修改!
修改 and 接收 select sql 函數 resultmap rom var 第一種 Public User selectUser(String name,String area); 對應的Mapper.xml <select id="selectUs
單鏈表反轉(三種方法總結)
題目:輸入一個連結串列,反轉連結串列後,輸出連結串列的所有元素。 方法一: 思路:從原連結串列的頭部一個一個取節點並插入到新連結串列的頭部 (1) struct ListNode{ int val; struct ListNode *nex
二叉樹非遞迴遍歷(三種+層序)
#include <iostream> #include <stdio.h> #include <queue> #include <stack> using namespace std; typedef struct BiTN
MQTT+ActiveMQ實現訊息推送(伺服器端java實現)
上一篇文章已經介紹了mqtt+activemq實現訊息推送移動端的實現,也介紹了利用自帶的web console進行訊息釋出的方法。但是在具體的專案應用中,當我們將需要將該訊息推送模組嵌入到一個後臺管理系統當中,我們就需要在web端來訪問activeMQ來進行訊
設計模式與應用:代理模式(三種詳解)
簡介 Proxy代理模式,是構造型的設計模式之一 代理模式為其他物件提供代理以控制這個物件的訪問。 所謂代理,是指具有與代理元(被代理物件)具有相同介面的類。client需要通過代理與被代理的目標類互動,代理類就是在互動的過程中(前後
ajax跨域問題(三種解決方案)
為什麼會出現跨域 跨域問題來源於JavaScript的同源策略,即只有 協議+主機名+埠號 (如存在)相同,則允許相互訪問。也就是說JavaScript只能訪問和操作自己域下的資源,不能訪問和操作其
Selenium練習四:百度搜索自動化指令碼(三種定位方式)
1. 實現百度搜索的自動化測試指令碼,需滿足要求如下: 1)瀏覽器至少選擇兩種(火狐+chrome/ie),關鍵詞為“福哥雜記 CSDN”; 2)指令碼檔案命名為“{組名}_{姓名}_百度搜索_{瀏覽器}_{指令碼序號}.py” 3)搜尋框和“百度一下”元素的定位方式,至少