mirror of
https://github.com/prdlk/leetcode.git
synced 2026-08-02 17:31:40 +00:00
init(docs): create docs site template with Fumapress and Waku
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
# 1365. How Many Numbers Are Smaller Than the Current Number
|
||||
|
||||
**Difficulty:** Easy
|
||||
**URL:** https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/
|
||||
**Topics:** Array, Hash Table, Sorting, Counting Sort
|
||||
|
||||
---
|
||||
|
||||
## 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.
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* 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: Begin by initializing a [Frequency Map]()
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
// Step 2: Sort the numbers by ascending order
|
||||
const sorted = Object.keys(freq).sort((a, b) => a - b);
|
||||
|
||||
// Step 3: Init a count of numbers smaller than the active number
|
||||
let count = 0;
|
||||
|
||||
// Step 4: Init a map to track number of values smaller for each number
|
||||
const smaller = {};
|
||||
|
||||
// Step 5: Iterate over the sorted list
|
||||
for (let num of sorted) {
|
||||
// Set count for active number
|
||||
smaller[num] = count;
|
||||
|
||||
// Update the count by frequency
|
||||
count += freq[num];
|
||||
}
|
||||
|
||||
// Step 6: Use original list and find number of smaller values than it
|
||||
return nums.map((n) => smaller[n]);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 1636. Sort Array by Increasing Frequency
|
||||
* Difficulty: Easy
|
||||
* https://leetcode.com/problems/sort-array-by-increasing-frequency/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given an array of integers nums, sort the array in increasing order
|
||||
* based on the frequency of the values. If multiple values have the same
|
||||
* frequency, sort them in decreasing order.
|
||||
*
|
||||
* Return the sorted array.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: nums = [1,1,2,2,2,3]
|
||||
* Output: [3,1,1,2,2,2]
|
||||
* Explanation: '3' has a frequency of 1, '1' has a frequency of 2, and
|
||||
* '2' has a frequency of 3.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: nums = [2,3,1,3,2]
|
||||
* Output: [1,3,3,2,2]
|
||||
* Explanation: '2' and '3' both have a frequency of 2, so they are
|
||||
* sorted in decreasing order.
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: nums = [-1,1,-6,4,5,-6,1,4,1]
|
||||
* Output: [5,-1,4,4,-6,-6,1,1,1]
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= nums.length <= 100
|
||||
*
|
||||
* • -100 <= nums[i] <= 100
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @return {number[]}
|
||||
*/
|
||||
var frequencySort = function (nums) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
return nums.sort((a, b) => freq[a] - freq[b] || b - a);
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 387. First Unique Character in a String
|
||||
* Difficulty: Easy
|
||||
* https://leetcode.com/problems/first-unique-character-in-a-string/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given a string s, find the first non-repeating character in it and
|
||||
* return its index. If it does not exist, return -1.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: s = "leetcode"
|
||||
*
|
||||
* Output: 0
|
||||
*
|
||||
* Explanation:
|
||||
*
|
||||
* The character 'l' at index 0 is the first character that does not
|
||||
* occur at any other index.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: s = "loveleetcode"
|
||||
*
|
||||
* Output: 2
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: s = "aabb"
|
||||
*
|
||||
* Output: -1
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= s.length <= 10^5
|
||||
*
|
||||
* • s consists of only lowercase English letters.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {number}
|
||||
*/
|
||||
var firstUniqChar = function (s) {
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
if (freq[s[i]] === 1) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 347. Top K Frequent Elements
|
||||
* Difficulty: Medium
|
||||
* https://leetcode.com/problems/top-k-frequent-elements/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given an integer array nums and an integer k, return the k most
|
||||
* frequent elements. You may return the answer in any order.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: nums = [1,1,1,2,2,3], k = 2
|
||||
*
|
||||
* Output: [1,2]
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: nums = [1], k = 1
|
||||
*
|
||||
* Output: [1]
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: nums = [1,2,1,2,1,2,3,1,3,2], k = 2
|
||||
*
|
||||
* Output: [1,2]
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= nums.length <= 10^5
|
||||
*
|
||||
* • -10^4 <= nums[i] <= 10^4
|
||||
*
|
||||
* • k is in the range [1, the number of unique elements in the array].
|
||||
*
|
||||
* • It is guaranteed that the answer is unique.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Follow up: Your algorithm's time complexity must be better than O(n
|
||||
* log n), where n is the array's size.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {number[]} nums
|
||||
* @param {number} k
|
||||
* @return {number[]}
|
||||
*/
|
||||
var topKFrequent = function (nums, k) {
|
||||
const freq = {};
|
||||
for (let n of nums) freq[n] = (freq[n] || 0) + 1;
|
||||
|
||||
return Object.keys(freq)
|
||||
.map(Number)
|
||||
.sort((a, b) => freq[b] - freq[a])
|
||||
.slice(0, k);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 451. Sort Characters By Frequency
|
||||
* Difficulty: Medium
|
||||
* https://leetcode.com/problems/sort-characters-by-frequency/
|
||||
*
|
||||
* ──────────────────────────────────────────────────
|
||||
*
|
||||
* Given a string s, sort it in decreasing order based on the frequency
|
||||
* of the characters. The frequency of a character is the number of times
|
||||
* it appears in the string.
|
||||
*
|
||||
* Return the sorted string. If there are multiple answers, return any
|
||||
* of them.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Example 1:
|
||||
*
|
||||
* Input: s = "tree"
|
||||
* Output: "eert"
|
||||
* Explanation: 'e' appears twice while 'r' and 't' both appear once.
|
||||
* So 'e' must appear before both 'r' and 't'. Therefore "eetr" is also
|
||||
* a valid answer.
|
||||
*
|
||||
* Example 2:
|
||||
*
|
||||
* Input: s = "cccaaa"
|
||||
* Output: "aaaccc"
|
||||
* Explanation: Both 'c' and 'a' appear three times, so both "cccaaa"
|
||||
* and "aaaccc" are valid answers.
|
||||
* Note that "cacaca" is incorrect, as the same characters must be
|
||||
* together.
|
||||
*
|
||||
* Example 3:
|
||||
*
|
||||
* Input: s = "Aabb"
|
||||
* Output: "bbAa"
|
||||
* Explanation: "bbaA" is also a valid answer, but "Aabb" is incorrect.
|
||||
* Note that 'A' and 'a' are treated as two different characters.
|
||||
*
|
||||
*
|
||||
*
|
||||
* Constraints:
|
||||
*
|
||||
* • 1 <= s.length <= 5 * 10^5
|
||||
*
|
||||
* • s consists of uppercase and lowercase English letters and digits.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @param {string} s
|
||||
* @return {string}
|
||||
*/
|
||||
var frequencySort = function (s) {
|
||||
// count the frequency of each character
|
||||
const freq = {};
|
||||
for (let c of s) freq[c] = (freq[c] || 0) + 1;
|
||||
|
||||
// sort the characters by frequency
|
||||
return s
|
||||
.split("")
|
||||
.sort((a, b) => freq[b] - freq[a] || a.localeCompare(b))
|
||||
.join("");
|
||||
};
|
||||
Reference in New Issue
Block a user