アルゴリズム-積み上げ順序、快速列-最小K個数、そして並べ替え出力
26422 ワード
アルゴリズム-積み上げ順序、快速列-最小K個数、そして並べ替え出力
1概要
1.1タイトルの出所
https://leetcode-cn.com/problems/smallest-k-lcci/
1.2テーマの説明
アルゴリズムを設計して,配列の中で最小のk個の数を見つける.このk個の数を任意の順序で返してもいいです.
例:
入力:arr=[1,3,5,7,2,4,6,8],k=4出力:[1,2,3,4]ヒント:
0<=len(arr)<=100000<=k<=min(100000,len(arr))
2構文
2.1トップヒープ
2.1.1問題を解く考え方は、トップヒープを採用し、最小のk個の数を保存する.具体的には、先に前のk個の数を預けて、そして大屋根の規則によって調整します.その後、他の数を遍歴して、より大きな場合は、ツリーをスキップします.より小さい場合は、この要素を置換し、山の頂部から を調整する.は、配列が最小のk個数 を保持する順序付けられた大屋根ヒープを得る.は積み重ねられた並べ替えを採用して、その後に並べ替えられた山を出力すればいいです.
2.1.2コード
最適:O(nlogn):最悪:O(nlogn):平均:O(nlogn)
2.1.4空間の複雑さ
O(min(n,k)
2.1.5注意事項
2.2快速修正
2.2.1問題を解く構想
急速な並べ替えの考えを考えると、1つの区切りが見つかります.左と区切り要素を合わせてK個の数があります.最小のk個の数が見つかります.
満足していない場合は状況に応じて左か右を探し続けます.
2.2.2コード
最適:O(n)最悪:O(n+n−1+n−2+n−n)=O(
2.2.4空間複雑度
O(1)
2.2.5注意事項 本のアルゴリズムはデータを全部メモリに読み込む必要があります.使用したい場合は、毎回1つまたは複数のデータを読み込むだけで、要素を区切って比較し、スコアは要素を隔てて小さいファイルに書き込まれます.今度はこの書類を読みに行きます.適当なものが見つかるまで.しかし、このような操作は複数回ディスクで読み書きされ、効率が非常に低いです. 元の配列を変更できない場合、元の配列を追加の空間記憶する必要があります. 2.3分散アルゴリズム
2.3.1問題を解く考え方
複数のマシン環境であれば、このタスクを複数のタスクに分割し、各タスクは前のKの大きさを見つけ、最後にもう一度統合して並べ替えると、グローバルの前のKの大きさが分かります.
2.4ソートアルゴリズム
2.4.1発泡体の並べ替え
2.4.1.1問題を解く考え方
毎回最大の数字を探し出して、K回だけで最大のK個の数を探し出すことができます.
時間複雑度O(K*N),空間複雑度O(N).
データを全部読み込む必要がありますが、海量データには適用されません.
2.4.2交換ソート
2.4.2.1問題を解く考え方
一番大きな要素を選ぶたびに、一番前の元素と位置を交換します.K回後に最大のK元素が得られた.
時間複雑度O(K*N),空間複雑度O(N).
スペースが足りないなら、毎回1つの数字だけ読み込むことができます.メモリに保存されている最大値と比較します.しかし、この方法は文書K回を読まなければなりません.性能が悪いです.
参考文献面接現場–どうやって10億数の中からトップ1000の数を探し出しますか?
1概要
1.1タイトルの出所
https://leetcode-cn.com/problems/smallest-k-lcci/
1.2テーマの説明
アルゴリズムを設計して,配列の中で最小のk個の数を見つける.このk個の数を任意の順序で返してもいいです.
例:
入力:arr=[1,3,5,7,2,4,6,8],k=4出力:[1,2,3,4]ヒント:
0<=len(arr)<=100000<=k<=min(100000,len(arr))
2構文
2.1トップヒープ
2.1.1問題を解く考え方
2.1.2コード
class Solution {
// 1. , k
// 2.
public int[] smallestK(int[] arr, int k) {
if(arr == null || arr.length == 0 || k<=0){
return new int[0];
}
int start;
//
int heapSize = arr.length < k ? arr.length : k;
//
if(heapSize % 2 == 0){
start = heapSize/2 - 1;
}else{
start = heapSize/2;
}
// ,
for(; start >= 0; start--){
adjustMaxHeap(arr, start, heapSize);
}
// , heap+1 ,
// ;
if(heapSize<arr.length){
int tmp = 0;
for(int i = heapSize;i<arr.length;i++){
if(arr[i]<arr[0]){
tmp = arr[0];
arr[0] = arr[i];
arr[i] = tmp;
adjustMaxHeap(arr,0,heapSize);
}
}
}
// , k , k
// : , ( )
for(int i = 0 ; i < heapSize; i++){
int tmp = arr[0];
arr[0] = arr[heapSize-i-1];
arr[heapSize-i-1] = tmp;
adjustMaxHeap(arr,0,heapSize-i-1);
}
// ,
int[] result = new int[heapSize];
for(int i = 0; i<heapSize; i++){
result[i] = arr[i];
}
return result;
}
public void adjustMaxHeap(int arr[], int start, int length){
if(length<0){
return;
}
//
int tmp = arr[start];
// ,
// 。 ,
for(int j = (start+1)*2 -1 ; j<length; j = (start+1)*2 -1 ){
// j
if(j < length){
// ,
if(j+1 < length){
j = arr[j] > arr[j+1] ? j : j + 1;
}
// ,
if(tmp > arr[j]){
break;
}
//
arr[start] = arr[j];
//
start = j;
}
}
// ,start
arr[start] = tmp;
}
}
2.1.3時間の複雑度最適:O(nlogn):最悪:O(nlogn):平均:O(nlogn)
2.1.4空間の複雑さ
O(min(n,k)
2.1.5注意事項
Arrays.sort(arr) Arrays.copyOf(arr, k)
などの方法を使わないでください.面接官は満足できないです.また、自分で面接をする時、関数名を忘れるかもしれません.2.2快速修正
2.2.1問題を解く構想
急速な並べ替えの考えを考えると、1つの区切りが見つかります.左と区切り要素を合わせてK個の数があります.最小のk個の数が見つかります.
満足していない場合は状況に応じて左か右を探し続けます.
2.2.2コード
class Solution {
// , ,
// K , k
public int[] getLeastNumbers(int[] arrs, int k) {
//
quickSort(arrs, 0, arrs.length-1, k);
// k
int[] result = new int[k];
for(int i = 0; i < k; i++){
result[i] = arrs[i];
}
return result;
}
// ,k k
public void quickSort(int[] arrs, int low, int high, int k){
if(low >= high){
// ,
return;
}
//
int tmp = arrs[low];
int i = low,j=high;
while(i<j){
// high , ,
while(i<j&&arrs[j]>tmp){
j--;
}
if(i<j){
// , i +1
// j ,
arrs[i++] = arrs[j];
}
// , ,
while(i<j&&arrs[i]<=tmp){
i++;
}
if(i<j){
arrs[j--] = arrs[i];
}
}
// ,i==j,
//
arrs[i] = tmp;
if(i + 1 - low < k){
// k, k-(i + 1 - low) ,
quickSort(arrs, i+1, high, k-(i + 1 - low));
} else if(i + 1 - low > k){
// k, k ,
quickSort(arrs, low, i-1, k);
}
}
}
2.2.3時間の複雑度最適:O(n)最悪:O(n+n−1+n−2+n−n)=O(
n^2
−(1+n)*n/2
)=O(n(n(n−1)/2)=O(n^2
)平均:O(n+n/2+n/4+…+1)=O(n)2.2.4空間複雑度
O(1)
2.2.5注意事項
2.3.1問題を解く考え方
複数のマシン環境であれば、このタスクを複数のタスクに分割し、各タスクは前のKの大きさを見つけ、最後にもう一度統合して並べ替えると、グローバルの前のKの大きさが分かります.
2.4ソートアルゴリズム
2.4.1発泡体の並べ替え
2.4.1.1問題を解く考え方
毎回最大の数字を探し出して、K回だけで最大のK個の数を探し出すことができます.
時間複雑度O(K*N),空間複雑度O(N).
データを全部読み込む必要がありますが、海量データには適用されません.
2.4.2交換ソート
2.4.2.1問題を解く考え方
一番大きな要素を選ぶたびに、一番前の元素と位置を交換します.K回後に最大のK元素が得られた.
時間複雑度O(K*N),空間複雑度O(N).
スペースが足りないなら、毎回1つの数字だけ読み込むことができます.メモリに保存されている最大値と比較します.しかし、この方法は文書K回を読まなければなりません.性能が悪いです.
参考文献