init(Docs): add docs site based on Fumapress and Fumadocs

This commit is contained in:
Prad Nukala
2026-07-11 16:09:08 -04:00
parent d7dfa1e45a
commit dc20248d5f
12 changed files with 1188 additions and 0 deletions
@@ -0,0 +1,58 @@
/*
* 1365. How Many Numbers Are Smaller Than the Current Number
* Difficulty: Easy
* https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
*
* ──────────────────────────────────────────────────
*
* Given the array nums, for each nums[i] find out how many numbers in
* the array are smaller than it. That is, for each nums[i] you have to
* count the number of valid j's such that j != i and nums[j] < nums[i].
*
* Return the answer in an array.
*
*
*
* Example 1:
*
* Input: nums = [8,1,2,2,3]
* Output: [4,0,1,1,3]
* Explanation:
* For nums[0]=8 there exist four smaller numbers than it (1, 2, 2 and
* 3).
* For nums[1]=1 does not exist any smaller number than it.
* For nums[2]=2 there exist one smaller number than it (1).
* For nums[3]=2 there exist one smaller number than it (1).
* For nums[4]=3 there exist three smaller numbers than it (1, 2 and 2).
*
* Example 2:
*
* Input: nums = [6,5,4,8]
* Output: [2,1,0,3]
*
* Example 3:
*
* Input: nums = [7,7,7,7]
* Output: [0,0,0,0]
*
*
*
* Constraints:
*
* • 2 <= nums.length <= 500
*
* • 0 <= nums[i] <= 100
*/
/**
* @param {number[]} nums
* @return {number[]}
*/
var smallerNumbersThanCurrent = function (nums) {
// Step 1: count the frequency of each number
const freq = {};
for (let x of nums) freq[x] = (freq[x] || 0) + 1;
return nums.map((x) => freq[x] || 0);
};
+149
View File
@@ -0,0 +1,149 @@
# 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 (0100). 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[a1] — 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.