diff --git a/Easy/Array/1365.md b/Easy/Array/1365.md deleted file mode 100644 index d948d60..0000000 --- a/Easy/Array/1365.md +++ /dev/null @@ -1,149 +0,0 @@ -# The Frequency Array + Prefix Sum Pattern - -**Solves:** LeetCode 1365 — How Many Numbers Are Smaller Than the Current Number -**Reusable for:** Any "count elements below/above X" problem where values live in a **small, bounded range**. - ---- - -## The One Insight That Makes This Work - -> If I know how many times each value appears, and I add those counts up from left to right, then `prefix[v]` tells me **how many elements are ≤ v** — instantly, for any v. - -That's it. Everything below is just executing this idea. - ---- - -## Step 1: Spot the Signal - -Read the constraints: - -``` -0 <= nums[i] <= 100 -``` - -Values are bounded to a tiny range (0–100). This is the **flashing neon sign** that says: don't sort, don't nest loops — build a frequency array indexed by value. - -**Rule of thumb:** value range ≤ ~10⁶ and you need counting/ranking? Frequency array. - ---- - -## Step 2: Count Every Value (the "bucket" pass) - -Make an array with one slot per possible value. Walk the input once. Each number votes for its own slot. - -```javascript -const freq = new Array(101).fill(0); // slots for values 0..100 -for (const x of nums) freq[x]++; -``` - -For `nums = [8, 1, 2, 2, 3]`: - -``` -value: 0 1 2 3 4 5 6 7 8 ... -freq: 0 1 2 1 0 0 0 0 1 ... -``` - -Read it as: "one 1, two 2s, one 3, one 8." - ---- - -## Step 3: Prefix Sum (the magic pass) - -Now transform `freq` in place: each slot becomes itself **plus everything before it**. - -```javascript -for (let i = 1; i < 101; i++) freq[i] += freq[i - 1]; -``` - -Same example after the pass: - -``` -value: 0 1 2 3 4 5 6 7 8 ... -freq: 0 1 3 4 4 4 4 4 5 ... -``` - -New meaning: `freq[v]` = **count of elements ≤ v**. - -- `freq[3] = 4` → four numbers are ≤ 3 (they are 1, 2, 2, 3) ✓ -- `freq[7] = 4` → still four numbers ≤ 7 ✓ - ---- - -## Step 4: Answer Queries in O(1) - -"How many numbers are **strictly smaller** than x?" is the same question as "how many numbers are **≤ x − 1**?" - -```javascript -return nums.map((x) => (x === 0 ? 0 : freq[x - 1])); -``` - -The `x === 0` guard exists because nothing can be smaller than the minimum possible value — and `freq[-1]` would be `undefined`. - -Trace on `[8, 1, 2, 2, 3]`: - -| x | lookup | answer | -|---|--------|--------| -| 8 | freq[7] | 4 | -| 1 | freq[0] | 0 | -| 2 | freq[1] | 1 | -| 2 | freq[1] | 1 | -| 3 | freq[2] | 3 | - -→ `[4, 0, 1, 1, 3]` ✓ - ---- - -## Full Solution - -```javascript -var smallerNumbersThanCurrent = function (nums) { - // 1. Bucket counts - const freq = new Array(101).fill(0); - for (const x of nums) freq[x]++; - - // 2. Prefix sum: freq[v] = count of elements <= v - for (let i = 1; i < 101; i++) freq[i] += freq[i - 1]; - - // 3. Strictly smaller than x == count of elements <= x-1 - return nums.map((x) => (x === 0 ? 0 : freq[x - 1])); -}; -``` - -**Complexity:** O(n + k) time, O(k) space, where k = value range (101 here). No sort, no log factor. - ---- - -## The Reusable Pattern (memorize this shape) - -``` -1. BUCKET — freq[value]++ for every element -2. PREFIX — freq[i] += freq[i-1] left to right -3. QUERY — freq[v] answers "how many ≤ v" in O(1) - freq[v-1] answers "how many < v" - n - freq[v] answers "how many > v" -``` - -### Where else this exact shape shows up - -| Problem | Same pattern, different query | -|---|---| -| **Counting Sort** | Prefix sums become final sorted positions | -| **LC 315 / rank queries** | "How many smaller" is literally a rank | -| **LC 1122 Relative Sort Array** | Bucket + walk buckets in order | -| **Radix sort digit pass** | Bucket by digit, prefix for placement | -| **Histogram percentiles** | freq[v] / n = percentile of v | -| **"How many in range [a, b]?"** | freq[b] − freq[a−1] — the prefix subtraction trick | - -### The generalization ladder - -- Values bounded and small → **frequency array** (this pattern) -- Values huge but few distinct → **coordinate compression** first, then this pattern -- Need updates between queries → upgrade prefix array to a **Fenwick tree (BIT)** — same idea, log-time updates - ---- - -## Common Mistakes - -1. **Returning `freq[x]` instead of `freq[x-1]`** — that counts elements ≤ x (including x itself and its duplicates). Off-by-one between "≤" and "<" is where this pattern bites. -2. **Forgetting the `x === 0` edge** — smallest possible value has nothing below it. -3. **Sizing the array to `nums.length` instead of the value range** — the buckets are indexed by *value*, not position.