数値の桁のリストをソートし、1 番目と 2 番目に大きい桁を取得すると、最適なO(n * log n)
時間で複雑になります ( Quick Sortを使用すると仮定します)。
別のアプローチを使用すると、パフォーマンスをいくらか向上させることができます。配列を分割 (並べ替え) (クイック ソートのように) すると、配列を 2 つの部分に分割するピボット値が得られます。左側の部分 (左側のサブアレイ)、大きい方は右側の部分 (右側のサブアレイ) にあります。ピボットのインデックスを確認します。
- 数字の配列のサイズから 2 を引いた値に等しい場合は、2 番目に大きい要素です (1 番目に大きい要素は、右側のサブ配列でその隣にあります)。
- ピボットのインデックスが数字の配列のサイズから 2 を引いたサイズより小さい場合は、右側のサブ配列に対して分割を繰り返します。
- ピボットのインデックスが数字の配列のサイズから 2 を引いたサイズよりも大きい場合は、左側のサブ配列の分割を繰り返します。
ある時点で、ピボットは配列の末尾から 2 番目の要素になります。これは、2 番目に大きい要素であり、最大の数が配列の末尾にあることを意味します (ピボットを取得する方法のため)。各パーティションの後、両方ではなく 1 つのサブアレイのみをパーティション化するため、時間の複雑さはクイックソートよりも優れています。
このアプローチを拡張して、1 番目と 2 番目に大きい桁だけでなく、k 番目 (任意の最大桁) の桁、および最大桁だけでなく最小桁も取得できます。
数日前に書いたコードをチェックしてください。
public Long selectKthElement(int left, int right, int k, Type type) {
int med = partitionIt(left, right);
if ((type.equals(Type.Smallest) && med == k - 1) || (type.equals(Type.Largest) && med == nElems - k)) {
return theArray[med];
} else if (type.equals(Type.Smallest) && med > k || type.equals(Type.Largest) && med > nElems - k) {
return selectKthElement(left, med - 1, k, type);
} else if (type.equals(Type.Smallest) && med < k || type.equals(Type.Largest) && med < nElems - k){
return selectKthElement(med + 1, right, k, type);
} else {
// impossible case, but the source code won't compile w/o the else
return null;
}
}
theArray
これは数値の桁の配列です。メソッドは配列を並べ替え、中央値のインデックスを返しますpartitionIt
。実装を自分で記述する方法を理解するか、Web を検索することができます。