@@ -387,13 +387,18 @@ where
387387
388388 impl < N > Eq for Element < N > { }
389389
390- let mut candidates = Vec :: with_capacity ( length . as_usize ( ) ) ;
390+ let mut candidates = Vec :: with_capacity ( amount . as_usize ( ) ) ;
391391 let mut index = N :: zero ( ) ;
392392 while index < length {
393393 let weight = weight ( index. as_usize ( ) ) . into ( ) ;
394394 if weight > 0.0 {
395395 let key = rng. random :: < f64 > ( ) . ln ( ) / weight;
396- candidates. push ( Element { index, key } ) ;
396+ if candidates. len ( ) < amount. as_usize ( ) {
397+ candidates. push ( Element { index, key } ) ;
398+ } else if key > candidates[ 0 ] . key {
399+ candidates[ 0 ] = Element { index, key } ;
400+ }
401+ candidates. sort_unstable ( ) ;
397402 } else if !( weight >= 0.0 ) {
398403 return Err ( WeightError :: InvalidWeight ) ;
399404 }
@@ -406,18 +411,7 @@ where
406411 return Err ( WeightError :: InsufficientNonZero ) ;
407412 }
408413
409- // Partially sort the array to find the `amount` elements with the greatest
410- // keys. Do this by using `select_nth_unstable` to put the elements with
411- // the *smallest* keys at the beginning of the list in `O(n)` time, which
412- // provides equivalent information about the elements with the *greatest* keys.
413- let ( _, mid, greater) = candidates. select_nth_unstable ( avail - amount. as_usize ( ) ) ;
414-
415- let mut result: Vec < N > = Vec :: with_capacity ( amount. as_usize ( ) ) ;
416- result. push ( mid. index ) ;
417- for element in greater {
418- result. push ( element. index ) ;
419- }
420- Ok ( IndexVec :: from ( result) )
414+ Ok ( IndexVec :: from ( candidates. iter ( ) . map ( |elt| elt. index ) . collect ( ) ) )
421415}
422416
423417/// Randomly sample exactly `amount` indices from `0..length`, using Floyd's
0 commit comments