Random Pick with Weight

MediumPrefix Sum · Binary Search · Randomized🧩 Binary SearchLeetCode #528 ↗Updated

Problem

You are given positive weights w, one per index. Implement a class Solution(int[] w) whose pickIndex() returns a random index i with probability w[i] / sum(w). Many picks are made after a single construction, so pickIndex should be fast.
Inputw = [1]; pickIndex()Output0 (the only index)
Inputw = [1,3]; many pickIndex()Output0 about 25% of the time, 1 about 75%

1 ≤ w.length ≤ 104  ·  1 ≤ w[i] ≤ 105  ·  ≤ 104 calls to pickIndex

Try it yourself

Java
class Solution {
    public Solution(int[] w) {
        
    }

    public int pickIndex() {
        
    }
}
Your code is saved in this browser.Submit on LeetCode ↗
Key insight
Lay the weights end to end on a number line of length total: index i owns a segment of length w[i]. Draw a uniform ticket in [0, total); the segment it lands in is the answer, and the prefix sums are the sorted segment ends, so binary search finds it.
PatternBinary Search

Instinct Sorted data, a rotated array, or find the min/max X that works where a yes/no test flips only once - halve the search space every step.

Memory hack Find the fence - every candidate reads NO NO NO YES YES, and binary search just walks to where the fence stands.

Open the Binary Search guide →

Approaches

Brute ForceExpanded Ticket Pool

Time O(total) build, O(1) pickSpace O(total)

Literally hand out tickets: put index i into a pool w[i] times and pick a uniformly random slot. Each index is chosen in proportion to how many tickets it holds.

Java
class Solution {
    Random rand = new Random();
    private final int[] pool; // index i appears w[i] times
    public Solution(int[] w) {
        int total = 0;
        for (int x : w) total += x;
        pool = new int[total];
        int k = 0;
        for (int i = 0; i < w.length; i++) {
            for (int c = 0; c < w[i]; c++) pool[k++] = i;
        }
    }
    public int pickIndex() {
        return pool[rand.nextInt(pool.length)];
    }
}

Instant picks, but total can reach 109 — the pool will not fit in memory.

At a glance

LevelApproachTimeSpace
Brute ForceExpanded Ticket PoolO(total) build, O(1) pickO(total)
BetterPrefix Sums + Linear ScanO(n) build, O(n) pickO(n)
OptimalPrefix Sums + Binary SearchO(n) build, O(log n) pickO(n)
Common pitfalls
  • Mixing ranges: ticket in [0, total) needs prefix[i] > r, not ≥.
  • Drawing a double and comparing loosely — off-by-one bias at boundaries.
  • Recomputing prefix sums inside pickIndex instead of once in the constructor.
Interview tips
  • Draw the number line with segments of length w[i] before writing code.
  • Check the boundary: the largest ticket total - 1 must map to the last index.
  • Mention the alias method for O(1) picks if asked about heavy query loads.
Pattern
Prefix sums + binary search → sampling or locating a position in a sequence of variable-length segments.
My notes saved in this browser