ExamplesBy LevelBy TopicLearning Paths
845 Fundamental

Randomized Quickselect

Functional Programming

Tutorial Video

Text description (accessibility)

This video demonstrates the "Randomized Quickselect" functional Rust example. Difficulty level: Fundamental. Key concepts covered: Functional Programming. Finding the kth smallest element in an unsorted array naively requires sorting: O(n log n). Key difference from OCaml: | Aspect | Rust | OCaml |

Tutorial

The Problem

Finding the kth smallest element in an unsorted array naively requires sorting: O(n log n). Quickselect finds it in O(n) expected time by using the partition step from quicksort but only recursing into one side. Choosing the pivot randomly avoids worst-case O(n^2) behavior from adversarial inputs. Practical uses: computing medians for statistics, percentile calculations in monitoring systems, streaming data analysis (p99 latency), and machine learning (median-based normalization). The deterministic variant (median-of-medians) guarantees O(n) worst-case but with higher constants.

🎯 Learning Outcomes

  • • Implement Lomuto or Hoare partition around a pivot, placing smaller elements left
  • • Choose pivot randomly to achieve O(n) expected time (not amortized — each call is O(n) expected)
  • • Recurse only into the side containing the target rank, halving the problem each expected step
  • • Understand why expected O(n): geometric series 1 + 1/2 + 1/4 + ... = 2 (expected recurrence)
  • • Distinguish from sorting: quickselect doesn't sort the discarded side — it literally ignores it
  • Code Example

    #![allow(clippy::all)]
    //! Placeholder

    Key Differences

    AspectRustOCaml
    In-place&mut [i32] slice partitionedarray mutation or copy
    Random pivotrand::thread_rng()Random.int n
    Three-way matchmatch pivot_pos.cmp(&k)compare pivot_pos k \|> match
    Rank adjustmentk - pivot_pos - 1Same arithmetic
    Worst caseO(n^2) with bad pivotsSame
    DeterministicMedian-of-medians variantSame

    OCaml Approach

    OCaml's quickselect uses Array.swap for the Lomuto partition. Random.int n provides the random pivot. The recursive call on a sub-array uses Array.sub (copying) or passes array bounds explicitly. OCaml's compare on the pivot position drives the three-case match. The functional style returns the kth element without modifying the array by working on a copy; the in-place version uses Array.blit for subarray passing.

    Full Source

    #![allow(clippy::all)]
    //! Placeholder

    Deep Comparison

    OCaml vs Rust: Randomized Quickselect

    Overview

    See the example.rs and example.ml files for detailed implementations.

    Key Differences

    AspectOCamlRust
    Type systemHindley-MilnerOwnership + traits
    MemoryGCZero-cost abstractions
    MutabilityExplicit refmut keyword
    Error handlingOption/ResultResult<T, E>

    See README.md for detailed comparison.

    Exercises

  • Implement median-of-medians pivot selection for guaranteed O(n) worst-case and compare speed with random pivot.
  • Find the top-k smallest elements (not just the kth) using quickselect plus partial sort on the left side.
  • Implement a streaming approximate median using the reservoir sampling or binning technique.
  • Measure the distribution of quickselect running time for n=10^6 across 1000 trials and compare with O(n) theory.
  • Implement the three-way partition (Dutch National Flag) to handle duplicate elements efficiently.
  • Open Source Repos