スタックの関連とtopK問題のJAVA実現
16146 ワード
title:スタックの関連およびtopK問題のJAVA実装date:2020-03-09 21:03:42 tags:
スタックの関連
スタックとは完全二叉木 各ノードの値は、その左右のサブノードに等しいか、またはそれ以下の値、すなわち、大きなトップスタックおよび小さなトップスタックである.
完全二叉木は配列を用いて格納されており,左右のポインタを用いる必要はなく,配列の下付きのみで左右サブノードにアクセスでき,0から計算を開始し,下付き
関連アクション
大きな天井を例にとると
ある配列要素をスタック化し、このノードからノードがその左右のサブノードの値より大きいまで:
ビルド:
ヒープのソート:
ヒープ要素を削除し、最後のリーフノードをヒープの上に配置し、ヒープ化します.
牛客には問題があり、最小のK個数を求めると、スタックを使って実現することができます.
タイトルの説明
n個の整数を入力し、その中で最も小さいK個の数を見つけます.例えば、4,5,1,6,2,7,3,8の8つの数字を入力すると、最小の4つの数字は>1,2,3,4である.
まず配列の前のK個の数を取り出して、大きなトップスタックを構築し、K+1番目の数からループを開始することができます.この数がトップ要素より小さい場合、この数をトップに置いてからスタック化します.
一次スタック化の時間的複雑度はO(logK)であり,配列O(n)を遍歴し,各要素がスタックに入ると仮定すると,時間的複雑度はO(nlongK)である.
スタックの関連
スタックとは
完全二叉木は配列を用いて格納されており,左右のポインタを用いる必要はなく,配列の下付きのみで左右サブノードにアクセスでき,0から計算を開始し,下付き
i
のノードの左ノードは2*i+1
,右ノードは2*i+2
である.関連アクション
大きな天井を例にとると
ある配列要素をスタック化し、このノードからノードがその左右のサブノードの値より大きいまで:
/**
*
*
* @param arr
* @param n
* @param i
*/
private static void heapify(int[] arr, int n, int i) {
while (true) {
//
int maxPos = i;
// (i * 2 + 1) ,
if (i * 2 + 1 <= n && arr[i] < arr[i * 2 + 1]) {
maxPos = i * 2 + 1;
}
// (i * 2 + 2) ,
if (i * 2 + 2 <= n && arr[maxPos] < arr[i * 2 + 2]) {
maxPos = i * 2 + 2;
}
//
if (maxPos == i) {
break;
}
//
swap(arr, i, maxPos);
//
i = maxPos;
}
}
ビルド:
/**
*
*
* @param arr
*/
private void buildHeap(int[] arr) {
// (arr.length - 1) / 2
// ,
for (int i = (arr.length - 1) / 2; i >= 0; i--) {
heapify(arr, arr.length - 1, i);
}
}
ヒープのソート:
/**
*
*
* 0
*
* @param arr
*/
public void sort(int[] arr) {
if (arr.length <= 1) {
return;
}
// 1、
buildHeap(arr);
// 2、
int k = arr.length - 1;
while (k > 0) {
// ( )
swap(arr, 0, k);
// ,
heapify(arr, --k, 0);
}
}
ヒープ要素を削除し、最後のリーフノードをヒープの上に配置し、ヒープ化します.
/**
* @param arr
* @param n
*/
public void delTop(int[] arr , int n){
if(n < 0) return;
arr[0] = arr[n];
heapify(arr , --n , 0);
}
牛客には問題があり、最小のK個数を求めると、スタックを使って実現することができます.
タイトルの説明
n個の整数を入力し、その中で最も小さいK個の数を見つけます.例えば、4,5,1,6,2,7,3,8の8つの数字を入力すると、最小の4つの数字は>1,2,3,4である.
まず配列の前のK個の数を取り出して、大きなトップスタックを構築し、K+1番目の数からループを開始することができます.この数がトップ要素より小さい場合、この数をトップに置いてからスタック化します.
一次スタック化の時間的複雑度はO(logK)であり,配列O(n)を遍歴し,各要素がスタックに入ると仮定すると,時間的複雑度はO(nlongK)である.
/**
* @param k top K ,
* @param a
* @return
*/
public int[] topK(int k , int[] a){
int count = 0;
int[] re = new int[k];
for (int i = 0; i < k; i++) {
re[i] = a[i];
}
// K
for (int i = (k - 1) / 2; i >= 0; i--) {
heapify(re, k-1, i);
}
for (int j = k; j < a.length; j++) {
if(re[0] > a[j]){
re[0] = a[j];
heapify(re , re.length - 1 , 0);
}
}
return re;
}