From 94b1e1af55f3d27e4046f41528616114312c6124 Mon Sep 17 00:00:00 2001 From: Prad Nukala Date: Tue, 25 Aug 2026 11:19:35 -0400 Subject: [PATCH] docs(docs): add LeetCode problem markdown pages and docs site assets --- apps/docs/.gitignore | 1 + apps/docs/content/(array)/1-two-sum.mdx | 47 +++ .../(array)/11-container-with-most-water.mdx | 48 +++ .../121-best-time-to-buy-and-sell-stock.mdx | 38 ++ ...rs-are-smaller-than-the-current-number.mdx | 63 ++++ ...value-to-get-positive-step-by-step-sum.mdx | 57 +++ .../(array)/1426-counting-elements.mdx | 45 +++ .../(array)/1480-running-sum-of-1d-array.mdx | 44 +++ apps/docs/content/(array)/15-3sum.mdx | 78 ++++ ...636-sort-array-by-increasing-frequency.mdx | 42 +++ .../167-two-sum-ii-input-array-is-sorted.mdx | 55 +++ .../docs/content/(array)/189-rotate-array.mdx | 42 +++ .../2090-k-radius-subarray-averages.mdx | 50 +++ .../(array)/217-contains-duplicate.mdx | 47 +++ .../238-product-of-array-except-self.mdx | 53 +++ .../content/(array)/268-missing-number.mdx | 55 +++ .../(array)/303-range-sum-query-immutable.mdx | 52 +++ .../33-search-in-rotated-sorted-array.mdx | 71 ++++ .../(array)/347-top-k-frequent-elements.mdx | 51 +++ .../(array)/42-trapping-rain-water.mdx | 36 ++ .../content/(array)/49-group-anagrams.mdx | 51 +++ .../(array)/560-subarray-sum-equals-k.mdx | 51 +++ .../content/(array)/704-binary-search.mdx | 56 +++ .../(array)/875-koko-eating-bananas.mdx | 62 ++++ .../(array)/977-squares-of-a-sorted-array.mdx | 55 +++ .../1832-check-if-the-sentence-is-pangram.mdx | 41 ++ .../(hash-table)/242-valid-anagram.mdx | 48 +++ ...387-first-unique-character-in-a-string.mdx | 47 +++ .../451-sort-characters-by-frequency.mdx | 49 +++ .../(two-pointers)/125-valid-palindrome.mdx | 51 +++ .../(two-pointers)/344-reverse-string.mdx | 45 +++ .../(two-pointers)/392-is-subsequence.mdx | 44 +++ apps/docs/content/index.mdx | 12 + apps/docs/content/progress.mdx | 9 + apps/docs/islands/ProgressDashboard.tsx | 351 ++++++++++++++++++ apps/docs/public/dependency-spine.html | 305 +++++++++++++++ apps/docs/public/dependency-spine.svg | 244 ++++++++++++ 37 files changed, 2496 insertions(+) create mode 100644 apps/docs/.gitignore create mode 100644 apps/docs/content/(array)/1-two-sum.mdx create mode 100644 apps/docs/content/(array)/11-container-with-most-water.mdx create mode 100644 apps/docs/content/(array)/121-best-time-to-buy-and-sell-stock.mdx create mode 100644 apps/docs/content/(array)/1365-how-many-numbers-are-smaller-than-the-current-number.mdx create mode 100644 apps/docs/content/(array)/1413-minimum-value-to-get-positive-step-by-step-sum.mdx create mode 100644 apps/docs/content/(array)/1426-counting-elements.mdx create mode 100644 apps/docs/content/(array)/1480-running-sum-of-1d-array.mdx create mode 100644 apps/docs/content/(array)/15-3sum.mdx create mode 100644 apps/docs/content/(array)/1636-sort-array-by-increasing-frequency.mdx create mode 100644 apps/docs/content/(array)/167-two-sum-ii-input-array-is-sorted.mdx create mode 100644 apps/docs/content/(array)/189-rotate-array.mdx create mode 100644 apps/docs/content/(array)/2090-k-radius-subarray-averages.mdx create mode 100644 apps/docs/content/(array)/217-contains-duplicate.mdx create mode 100644 apps/docs/content/(array)/238-product-of-array-except-self.mdx create mode 100644 apps/docs/content/(array)/268-missing-number.mdx create mode 100644 apps/docs/content/(array)/303-range-sum-query-immutable.mdx create mode 100644 apps/docs/content/(array)/33-search-in-rotated-sorted-array.mdx create mode 100644 apps/docs/content/(array)/347-top-k-frequent-elements.mdx create mode 100644 apps/docs/content/(array)/42-trapping-rain-water.mdx create mode 100644 apps/docs/content/(array)/49-group-anagrams.mdx create mode 100644 apps/docs/content/(array)/560-subarray-sum-equals-k.mdx create mode 100644 apps/docs/content/(array)/704-binary-search.mdx create mode 100644 apps/docs/content/(array)/875-koko-eating-bananas.mdx create mode 100644 apps/docs/content/(array)/977-squares-of-a-sorted-array.mdx create mode 100644 apps/docs/content/(hash-table)/1832-check-if-the-sentence-is-pangram.mdx create mode 100644 apps/docs/content/(hash-table)/242-valid-anagram.mdx create mode 100644 apps/docs/content/(hash-table)/387-first-unique-character-in-a-string.mdx create mode 100644 apps/docs/content/(hash-table)/451-sort-characters-by-frequency.mdx create mode 100644 apps/docs/content/(two-pointers)/125-valid-palindrome.mdx create mode 100644 apps/docs/content/(two-pointers)/344-reverse-string.mdx create mode 100644 apps/docs/content/(two-pointers)/392-is-subsequence.mdx create mode 100644 apps/docs/content/index.mdx create mode 100644 apps/docs/content/progress.mdx create mode 100644 apps/docs/islands/ProgressDashboard.tsx create mode 100644 apps/docs/public/dependency-spine.html create mode 100644 apps/docs/public/dependency-spine.svg diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore new file mode 100644 index 0000000..2c0d364 --- /dev/null +++ b/apps/docs/.gitignore @@ -0,0 +1 @@ +.blume-verify/ diff --git a/apps/docs/content/(array)/1-two-sum.mdx b/apps/docs/content/(array)/1-two-sum.mdx new file mode 100644 index 0000000..6c7753f --- /dev/null +++ b/apps/docs/content/(array)/1-two-sum.mdx @@ -0,0 +1,47 @@ +--- +title: '1. Two Sum' +description: You are given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target +sidebar: + label: 'Two Sum' + badge: 'Easy' +--- + +Hash Table + +::::warning +Can you come up with an algorithm that is less than O(n^2) time complexity? +:::: + +### Example 1: +- Input: `nums = [2,7,11,15], target = 9` +- Output: `[0,1]` +- Explanation: Because `nums[0] + nums[1]` == `9`, we return [0, 1]. + +### Example 2: +- Input: `nums = [3,2,4], target = 6` +- Output: `[1,2]` + +### Example 3: +- Input: `nums = [3,3], target = 6` +- Output: `[0,1]` + +### Constraints: + +- `2 <= nums.length <= 10^4` +- `-10^9 <= nums[i] <= 10^9` +- `-10^9 <= target <= 10^9` +- Only one valid answer exists. + +## Solution + +```py +class Solution: + def twoSum(self, nums: List[int], target: int) -> List[int]: + seen = {} + for i, num in enumerate(nums): + complement = target - num + if complement in seen: + return [seen[complement], i] + seen[num] = i + return [] +``` diff --git a/apps/docs/content/(array)/11-container-with-most-water.mdx b/apps/docs/content/(array)/11-container-with-most-water.mdx new file mode 100644 index 0000000..0b01c2e --- /dev/null +++ b/apps/docs/content/(array)/11-container-with-most-water.mdx @@ -0,0 +1,48 @@ +--- +title: '11. Container With Most Water' +description: You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the i^th line are (i, 0) and (i, height[i]) +sidebar: + label: 'Container With Most Water' + badge: 'Medium' +--- + +Two Pointers + +::::warning +Notice that you may not slant the container. +:::: + +### Example 1: +- Input: `height = [1,8,6,2,5,4,8,3,7]` +- Output: `49` +- Explanation: The above vertical lines are represented by array `[1,8,6,2,5,4,8,3,7]`. In this case, the max area of water (blue section) the container can contain is `49`. + +### Example 2: +- Input: `height = [1,1]` +- Output: `1` + +### Constraints: + +- `n == height.length` +- `2 <= n <= 10^5` +- `0 <= height[i] <= 10^4` + +## Solution + +```py +class Solution: + def maxArea(self, height: List[int]) -> int: # noqa: F821 + res = 0 + left = 0 + right = len(height) - 1 + + while left < right: + area = (right - left) * min(height[left], height[right]) + res = max(res, area) + if height[left] < height[right]: + left += 1 + else: + right -= 1 + + return res +``` diff --git a/apps/docs/content/(array)/121-best-time-to-buy-and-sell-stock.mdx b/apps/docs/content/(array)/121-best-time-to-buy-and-sell-stock.mdx new file mode 100644 index 0000000..d9c2243 --- /dev/null +++ b/apps/docs/content/(array)/121-best-time-to-buy-and-sell-stock.mdx @@ -0,0 +1,38 @@ +--- +title: '121. Best Time to Buy and Sell Stock' +description: You are given an array prices where prices[i] is the price of a given stock on the i^th day +sidebar: + label: 'Best Time to Buy and Sell Stock' + badge: 'Easy' +--- + +Sliding Window + +### Example 1: +- Input: `prices = [7,1,5,3,6,4]` +- Output: `5` +- Explanation: Buy on day `2` (price = `1`) and sell on day `5` (price = `6`), profit = `6-1 = 5`. Note that buying on day `2` and selling on day `1` is not allowed because you must buy before you sell. + +### Example 2: +- Input: `prices = [7,6,4,3,1]` +- Output: `0` +- Explanation: In this case, no transactions are done and the max profit = `0`. + +### Constraints: + +- `1 <= prices.length <= 10^5` +- `0 <= prices[i] <= 10^4` + +## Solution + +```py +class Solution: + def maxProfit(self, prices: List[int]) -> int: + left = min(prices) + for right in range(len(prices)): + while curr > left: + curr -= prices[left] + left += 1 + ans = max(ans, curr) + return ans +``` diff --git a/apps/docs/content/(array)/1365-how-many-numbers-are-smaller-than-the-current-number.mdx b/apps/docs/content/(array)/1365-how-many-numbers-are-smaller-than-the-current-number.mdx new file mode 100644 index 0000000..e250cd2 --- /dev/null +++ b/apps/docs/content/(array)/1365-how-many-numbers-are-smaller-than-the-current-number.mdx @@ -0,0 +1,63 @@ +--- +title: '1365. How Many Numbers Are Smaller Than the Current Number' +description: 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] +sidebar: + label: 'How Many Numbers Are Smaller Than the Current Number' + badge: 'Easy' +--- + +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` + +## Solution + +```js +/** + * @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]); +}; +``` diff --git a/apps/docs/content/(array)/1413-minimum-value-to-get-positive-step-by-step-sum.mdx b/apps/docs/content/(array)/1413-minimum-value-to-get-positive-step-by-step-sum.mdx new file mode 100644 index 0000000..5d4bf8b --- /dev/null +++ b/apps/docs/content/(array)/1413-minimum-value-to-get-positive-step-by-step-sum.mdx @@ -0,0 +1,57 @@ +--- +title: '1413. Minimum Value to Get Positive Step by Step Sum' +description: Given an array of integers nums, you start with an initial positive value startValue +sidebar: + label: 'Minimum Value to Get Positive Step by Step Sum' + badge: 'Easy' +--- + +Array + +### Example 1: +- Input: `nums = [-3,2,-3,4,2]` +- Output: `5` +- Explanation: If you choose `startValue = 4`, in the third iteration your step by step sum is less than `1`. + +``` +step by step sum +startValue = 4 | startValue = 5 | nums + (4 -3 ) = 1 | (5 -3 ) = 2 | -3 + (1 +2 ) = 3 | (2 +2 ) = 4 | 2 + (3 -3 ) = 0 | (4 -3 ) = 1 | -3 + (0 +4 ) = 4 | (1 +4 ) = 5 | 4 + (4 +2 ) = 6 | (5 +2 ) = 7 | 2 +``` + +### Example 2: +- Input: `nums = [1,2]` +- Output: `1` +- Explanation: Minimum start value should be positive. + +### Example 3: +- Input: `nums = [1,-2,-3]` +- Output: `5` + +### Constraints: + +- `1 <= nums.length <= 100` +- `-100 <= nums[i] <= 100` + +## Solution + +```js +/** + * @param {number[]} nums + * @return {number} + */ +var minStartValue = function(nums) { + let prefix = [nums[0]]; + // Make prefix sum start at 1 after initializing seed value + for (let i = 1; i < nums.length; i++){ + prefix.push(prefix[i - 1] + nums[i]); + } + + let min = Math.min(...prefix); + return Math.max(1, 1 - min); +}; +``` diff --git a/apps/docs/content/(array)/1426-counting-elements.mdx b/apps/docs/content/(array)/1426-counting-elements.mdx new file mode 100644 index 0000000..ae081da --- /dev/null +++ b/apps/docs/content/(array)/1426-counting-elements.mdx @@ -0,0 +1,45 @@ +--- +title: '1426. Counting Elements' +description: Given an integer array arr, count how many elements x there are, such that x + 1 is also in arr. If there are duplicates in arr, count them separately +sidebar: + label: 'Counting Elements' + badge: 'Easy' +--- + +Array + +### Example 1: +- Input: `arr = [1,2,3]` +- Output: `2` +- Explanation: `1` and `2` are counted cause `2` and `3` are in `arr`. + +### Example 2: +- Input: `arr = [1,1,3,3,5,5,7,7]` +- Output: `0` +- Explanation: No numbers are counted, cause there is no `2`, `4`, `6`, or `8` in `arr`. + +### Constraints: + +- `1 <= arr.length <= 1000` +- `0 <= arr[i] <= 1000` + +## Solution + +```js +/** + * @param {number[]} arr + * @return {number} + */ +var countElements = function(arr) { + let arrSet = new Set(arr); + let count = 0; + + for (let n of arr) { + let sum = n + 1; + if (arrSet.has(sum)) { + count++; + } + } + return count; +}; +``` diff --git a/apps/docs/content/(array)/1480-running-sum-of-1d-array.mdx b/apps/docs/content/(array)/1480-running-sum-of-1d-array.mdx new file mode 100644 index 0000000..a3aef67 --- /dev/null +++ b/apps/docs/content/(array)/1480-running-sum-of-1d-array.mdx @@ -0,0 +1,44 @@ +--- +title: '1480. Running Sum of 1d Array' +description: Given an array nums. We define a running sum of an array as runningSum[i] = sum(nums[0]…nums[i]) +sidebar: + label: 'Running Sum of 1d Array' + badge: 'Easy' +--- + +Array + +### Example 1: +- Input: `nums = [1,2,3,4]` +- Output: `[1,3,6,10]` +- Explanation: Running sum is obtained as follows: `[1, 1+2, 1+2+3, 1+2+3+4]`. + +### Example 2: +- Input: `nums = [1,1,1,1,1]` +- Output: `[1,2,3,4,5]` +- Explanation: Running sum is obtained as follows: `[1, 1+1, 1+1+1, 1+1+1+1, 1+1+1+1+1]`. + +### Example 3: +- Input: `nums = [3,1,2,10,1]` +- Output: `[3,4,6,16,17]` + +### Constraints: + +- `1 <= nums.length <= 1000` +- `-10^6 <= nums[i] <= 10^6` + +## Solution + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +var runningSum = function(nums) { + let prefix = [nums[0]]; + for (let i = 1; i < nums.length; i++){ + prefix.push(prefix[i - 1] + nums[i]); + } + return prefix; +}; +``` diff --git a/apps/docs/content/(array)/15-3sum.mdx b/apps/docs/content/(array)/15-3sum.mdx new file mode 100644 index 0000000..9ca8ec4 --- /dev/null +++ b/apps/docs/content/(array)/15-3sum.mdx @@ -0,0 +1,78 @@ +--- +title: '15. 3Sum' +description: Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0 +sidebar: + label: '3Sum' + badge: 'Medium' +--- + +Two Pointers + +::::warning +Notice that the solution set must not contain duplicate triplets. +:::: + +### Example 1: +- Input: `nums = [-1,0,1,2,-1,-4]` +- Output: `[[-1,-1,2],[-1,0,1]]` +- Explanation: `nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0`. `nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0`. `nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0`. The distinct triplets are `[-1,0,1]` and `[-1,-1,2]`. Notice that the order of the output and the order of the triplets does not matter. + +### Example 2: +- Input: `nums = [0,1,1]` +- Output: `[]` +- Explanation: The only possible triplet does not sum up to `0`. + +### Example 3: +- Input: `nums = [0,0,0]` +- Output: `[[0,0,0]]` +- Explanation: The only possible triplet sums up to `0`. + +### Constraints: + +- `3 <= nums.length <= 3000` +- `-10^5 <= nums[i] <= 10^5` + +## Solution + +```py +class Solution: + def threeSum(self, nums: list[int]) -> list[list[int]]: + nums.sort() + result = [] + n = len(nums) + + for i in range(n): + # skip all zero + if i > 0 and nums[i] == nums[i - 1]: + continue + + # two pointers + left = i + 1 + right = n - 1 + target = -nums[i] + + while left < right: + current = nums[left] + nums[right] + + if current == target: + result.append([nums[i], nums[left], nums[right]]) + + # skip duplicates + while left < right and nums[left] == nums[left + 1]: + left += 1 + while left < right and nums[right] == nums[right - 1]: + right -= 1 + + # shift pointers + left += 1 + right -= 1 + + # since sorted, if current < target, then move left + elif current < target: + left += 1 + # since sorted, if current > target, then move right + else: + right -= 1 + + return result +``` diff --git a/apps/docs/content/(array)/1636-sort-array-by-increasing-frequency.mdx b/apps/docs/content/(array)/1636-sort-array-by-increasing-frequency.mdx new file mode 100644 index 0000000..eafaf3a --- /dev/null +++ b/apps/docs/content/(array)/1636-sort-array-by-increasing-frequency.mdx @@ -0,0 +1,42 @@ +--- +title: '1636. Sort Array by Increasing Frequency' +description: 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 +sidebar: + label: 'Sort Array by Increasing Frequency' + badge: 'Easy' +--- + +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` + +## Solution + +```js +/** + * @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); +}; +``` diff --git a/apps/docs/content/(array)/167-two-sum-ii-input-array-is-sorted.mdx b/apps/docs/content/(array)/167-two-sum-ii-input-array-is-sorted.mdx new file mode 100644 index 0000000..0853ffd --- /dev/null +++ b/apps/docs/content/(array)/167-two-sum-ii-input-array-is-sorted.mdx @@ -0,0 +1,55 @@ +--- +title: '167. Two Sum II - Input Array Is Sorted' +description: Given a 1-indexed array of integers numbers that is already sorted in non-decreasing order, find two numbers such that they add up to a specific target number. Let these two numbers be numbers[index1] and numbers[index2] where 1 <= index1 < index2 <= numbers.length +sidebar: + label: 'Two Sum II - Input Array Is Sorted' + badge: 'Medium' +--- + +Two Pointers + +::::warning +Your solution must use only constant extra space. +:::: + +### Example 1: +- Input: `numbers = [2,7,11,15], target = 9` +- Output: `[1,2]` +- Explanation: The sum of `2` and `7` is `9`. Therefore, `index1 = 1`, `index2 = 2`. We return `[1, 2]`. + +### Example 2: +- Input: `numbers = [2,3,4], target = 6` +- Output: `[1,3]` +- Explanation: The sum of `2` and `4` is `6`. Therefore `index1 = 1`, `index2 = 3`. We return `[1, 3]`. + +### Example 3: +- Input: `numbers = [-1,0], target = -1` +- Output: `[1,2]` +- Explanation: The sum of `-1` and `0` is `-1`. Therefore `index1 = 1`, `index2 = 2`. We return `[1, 2]`. + +### Constraints: + +- `2 <= numbers.length <= 3 * 10^4` +- `-1000 <= numbers[i] <= 1000` +- `numbers` is sorted in non-decreasing order. +- `-1000 <= target <= 1000` +- The tests are generated such that there is exactly one solution. + +## Solution + +```py +class Solution: + def twoSum(self, numbers: List[int], target: int) -> List[int]: + i = 0 + j = len(numbers) - 1 + + while i < j: + c = numbers[i] + numbers[j] + if c == target: + return [i + 1, j + 1] + elif c < target: + i+=1 + else: + j-=1 + return [] +``` diff --git a/apps/docs/content/(array)/189-rotate-array.mdx b/apps/docs/content/(array)/189-rotate-array.mdx new file mode 100644 index 0000000..260493f --- /dev/null +++ b/apps/docs/content/(array)/189-rotate-array.mdx @@ -0,0 +1,42 @@ +--- +title: '189. Rotate Array' +description: Given an integer array nums, rotate the array to the right by k steps, where k is non-negative +sidebar: + label: 'Rotate Array' + badge: 'Medium' +--- + +Two Pointers + +::::warning +Try to come up with as many solutions as you can. There are at least three different ways to solve this problem. Could you do it in-place with `O(1)` extra space? +:::: + +### Example 1: +- Input: `nums = [1,2,3,4,5,6,7], k = 3` +- Output: `[5,6,7,1,2,3,4]` +- Explanation: rotate 1 steps to the right: `[7,1,2,3,4,5,6]` rotate 2 steps to the right: `[6,7,1,2,3,4,5]` rotate 3 steps to the right: `[5,6,7,1,2,3,4]` + +### Example 2: +- Input: `nums = [-1,-100,3,99], k = 2` +- Output: `[3,99,-1,-100]` +- Explanation: rotate 1 steps to the right: `[99,-1,-100,3]` rotate 2 steps to the right: `[3,99,-1,-100]` + +### Constraints: + +- `1 <= nums.length <= 10^5` +- `-2^31 <= nums[i] <= 2^31 - 1` +- `0 <= k <= 10^5` + +## Solution + +```js +/** + * @param {number[]} nums + * @param {number} k + * @return {void} Do not return anything, modify nums in-place instead. + */ +var rotate = function(nums, k) { + +}; +``` diff --git a/apps/docs/content/(array)/2090-k-radius-subarray-averages.mdx b/apps/docs/content/(array)/2090-k-radius-subarray-averages.mdx new file mode 100644 index 0000000..652f779 --- /dev/null +++ b/apps/docs/content/(array)/2090-k-radius-subarray-averages.mdx @@ -0,0 +1,50 @@ +--- +title: '2090. K Radius Subarray Averages' +description: You are given a 0-indexed array nums of n integers, and an integer k +sidebar: + label: 'K Radius Subarray Averages' + badge: 'Medium' +--- + +Array + +### Example 1: +- Input: `nums = [7,4,3,9,1,8,5,2,6], k = 3` +- Output: `[-1,-1,-1,5,4,4,-1,-1,-1]` +- Explanation: + - `avg[0]`, `avg[1]`, and `avg[2]` are `-1` because there are less than `k` elements before each index. + - The sum of the subarray centered at index `3` with radius `3` is: `7 + 4 + 3 + 9 + 1 + 8 + 5 = 37`. Using integer division, `avg[3] = 37 / 7 = 5`. + - For the subarray centered at index `4`, `avg[4] = (4 + 3 + 9 + 1 + 8 + 5 + 2) / 7 = 4`. + - For the subarray centered at index `5`, `avg[5] = (3 + 9 + 1 + 8 + 5 + 2 + 6) / 7 = 4`. + - `avg[6]`, `avg[7]`, and `avg[8]` are `-1` because there are less than `k` elements after each index. + +### Example 2: +- Input: `nums = [100000], k = 0` +- Output: `[100000]` +- Explanation: + - The sum of the subarray centered at index `0` with radius `0` is: `100000`. `avg[0] = 100000 / 1 = 100000`. + +### Example 3: +- Input: `nums = [8], k = 100000` +- Output: `[-1]` +- Explanation: + - `avg[0]` is `-1` because there are less than `k` elements before and after index `0`. + +### Constraints: + +- `n == nums.length` +- `1 <= n <= 10^5` +- `0 <= nums[i], k <= 10^5` + +## Solution + +```js +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var getAverages = function(nums, k) { + +}; +``` diff --git a/apps/docs/content/(array)/217-contains-duplicate.mdx b/apps/docs/content/(array)/217-contains-duplicate.mdx new file mode 100644 index 0000000..bde42cd --- /dev/null +++ b/apps/docs/content/(array)/217-contains-duplicate.mdx @@ -0,0 +1,47 @@ +--- +title: '217. Contains Duplicate' +description: Given an integer array nums, return true if any value appears at least twice in the array, and return false if every element is distinct +sidebar: + label: 'Contains Duplicate' + badge: 'Easy' +--- + +Hash Table + +### Example 1: +- Input: `nums = [1,2,3,1]` +- Output: `true` +- Explanation: The element `1` occurs at the indices `0` and `3`. + +### Example 2: +- Input: `nums = [1,2,3,4]` +- Output: `false` +- Explanation: All elements are distinct. + +### Example 3: +- Input: `nums = [1,1,1,3,3,4,3,2,4,2]` +- Output: `true` + +### Constraints: + +- `1 <= nums.length <= 10^5` +- `-10^9 <= nums[i] <= 10^9` + +## Solution + +```js +/** + * @param {number[]} nums + * @return {boolean} + */ +var containsDuplicate = function(nums) { + const freq = {}; + for (let n of nums) { + freq[n] = (freq[n] || 0) + 1; + if (freq[n] >= 2) { + return true; + } + } + return false; +}; +``` diff --git a/apps/docs/content/(array)/238-product-of-array-except-self.mdx b/apps/docs/content/(array)/238-product-of-array-except-self.mdx new file mode 100644 index 0000000..647c1ea --- /dev/null +++ b/apps/docs/content/(array)/238-product-of-array-except-self.mdx @@ -0,0 +1,53 @@ +--- +title: '238. Product of Array Except Self' +description: Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i] +sidebar: + label: 'Product of Array Except Self' + badge: 'Medium' +--- + +Prefix Sum + +::::warning +You must write an algorithm that runs in O(n) time and without using the division operation. +Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.) +:::: + +### Example 1: +- Input: `nums = [1,2,3,4]` +- Output: `[24,12,8,6]` + +### Example 2: +- Input: `nums = [-1,1,0,-3,3]` +- Output: `[0,0,9,0,0]` + +### Constraints: + +- `2 <= nums.length <= 10^5` +- `-30 <= nums[i] <= 30` +- The input is generated such that `answer[i]` is guaranteed to fit in a 32-bit integer. + +## Solution + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +var productExceptSelf = function(nums) { + const n = nums.length; + const answer = new Array(n).fill(1); + const rightArr = new Array(n).fill(1); + + for (let i = 1; i < n; i++) { + answer[i] = nums[i - 1] * answer[i - 1]; + } + for (let i = n - 2; i >= 0; i--) { + rightArr[i] = nums[i + 1] * rightArr[i + 1]; + } + for (let i = 0; i < n; i++) { + answer[i] *= rightArr[i]; + } + return answer; +}; +``` diff --git a/apps/docs/content/(array)/268-missing-number.mdx b/apps/docs/content/(array)/268-missing-number.mdx new file mode 100644 index 0000000..36100cf --- /dev/null +++ b/apps/docs/content/(array)/268-missing-number.mdx @@ -0,0 +1,55 @@ +--- +title: '268. Missing Number' +description: Given an array nums containing n distinct numbers in the range [0, n], return the only number in the range that is missing from the array +sidebar: + label: 'Missing Number' + badge: 'Easy' +--- + +Array + +::::warning +Could you implement a solution using only O(1) extra space complexity and O(n) runtime complexity? +:::: + +### Example 1: +- Input: `nums = [3,0,1]` +- Output: `2` +- Explanation: `n = 3` since there are `3` numbers, so all numbers are in the range `[0,3]`. `2` is the missing number in the range since it does not appear in `nums`. + +### Example 2: +- Input: `nums = [0,1]` +- Output: `2` +- Explanation: `n = 2` since there are `2` numbers, so all numbers are in the range `[0,2]`. `2` is the missing number in the range since it does not appear in `nums`. + +### Example 3: +- Input: `nums = [9,6,4,2,3,5,7,0,1]` +- Output: `8` +- Explanation: `n = 9` since there are `9` numbers, so all numbers are in the range `[0,9]`. `8` is the missing number in the range since it does not appear in `nums`. + +### Constraints: + +- `n == nums.length` +- `1 <= n <= 10^4` +- `0 <= nums[i] <= n` +- All the numbers of `nums` are unique. + +## Solution + +```js +/** + * @param {number[]} nums + * @return {number} + */ +var missingNumber = function(nums) { + const numSet = new Set(nums); + const expectedCount = nums.length + 1; + + for (let i = 0; i < expectedCount; i++){ + if(!numSet.has(i)){ + return i; + } + } + return -1; +}; +``` diff --git a/apps/docs/content/(array)/303-range-sum-query-immutable.mdx b/apps/docs/content/(array)/303-range-sum-query-immutable.mdx new file mode 100644 index 0000000..bbf2916 --- /dev/null +++ b/apps/docs/content/(array)/303-range-sum-query-immutable.mdx @@ -0,0 +1,52 @@ +--- +title: '303. Range Sum Query - Immutable' +description: Given an integer array nums, handle multiple queries of the following type +sidebar: + label: 'Range Sum Query - Immutable' + badge: 'Easy' +--- + +Prefix Sum + +### Example 1: +- Input: `["NumArray", "sumRange", "sumRange", "sumRange"]` `[[[-2, 0, 3, -5, 2, -1]], [0, 2], [2, 5], [0, 5]]` +- Output: `[null, 1, -1, -3]` +- Explanation: `NumArray numArray = new NumArray([-2, 0, 3, -5, 2, -1]);` `numArray.sumRange(0, 2); // return (-2) + 0 + 3 = 1` `numArray.sumRange(2, 5); // return 3 + (-5) + 2 + (-1) = -1` `numArray.sumRange(0, 5); // return (-2) + 0 + 3 + (-5) + 2 + (-1) = -3` + +### Constraints: + +- `1 <= nums.length <= 10^4` +- `-10^5 <= nums[i] <= 10^5` +- `0 <= left <= right < nums.length` +- At most `10^4` calls will be made to `sumRange`. + +## Solution + +```js +/** + * @param {number[]} nums + */ +class NumArray { + constructor(nums) { + this.prefix = [0]; + for (let n of nums){ + this.prefix.push(this.prefix[this.prefix.length - 1] + n); + } + } + /** + * @param {number} left + * @param {number} right + * @return {number} + */ + sumRange(left, right) { + return this.prefix[right + 1] - this.prefix[left]; + } +} + + +/** + * Your NumArray object will be instantiated and called as such: + * var obj = new NumArray(nums) + * var param_1 = obj.sumRange(left,right) + */ +``` diff --git a/apps/docs/content/(array)/33-search-in-rotated-sorted-array.mdx b/apps/docs/content/(array)/33-search-in-rotated-sorted-array.mdx new file mode 100644 index 0000000..185460a --- /dev/null +++ b/apps/docs/content/(array)/33-search-in-rotated-sorted-array.mdx @@ -0,0 +1,71 @@ +--- +title: '33. Search in Rotated Sorted Array' +description: There is an integer array nums sorted in ascending order (with distinct values) +sidebar: + label: 'Search in Rotated Sorted Array' + badge: 'Medium' +--- + +Binary Search + +::::warning +You must write an algorithm with O(log n) runtime complexity. +:::: + +### Example 1: +- Input: `nums = [4,5,6,7,0,1,2], target = 0` +- Output: `4` + +### Example 2: +- Input: `nums = [4,5,6,7,0,1,2], target = 3` +- Output: `-1` + +### Example 3: +- Input: `nums = [1], target = 0` +- Output: `-1` + +### Constraints: + +- `1 <= nums.length <= 5000` +- `-10^4 <= nums[i] <= 10^4` +- All values of `nums` are unique. +- `nums` is an ascending array that is possibly rotated. +- `-10^4 <= target <= 10^4` + +## Solution + +```js +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var search = function(nums, target) { + let l = 0, r = nums.length - 1; + + while (l <= r){ + let mid = Math.floor((l + r)/2); + if (target === nums[mid]) { + return mid + } + + // Left sorted portion + if (nums[l] <= nums[mid]){ + if (target > nums[mid] || target < nums[l]){ + l = mid + 1; + }else{ + r = mid - 1; + } + } + // Right sorted portion + else{ + if(target < nums[mid] || target > nums[r]){ + r = mid - 1; + }else{ + l = mid + 1; + } + } + } + return -1; +}; +``` diff --git a/apps/docs/content/(array)/347-top-k-frequent-elements.mdx b/apps/docs/content/(array)/347-top-k-frequent-elements.mdx new file mode 100644 index 0000000..cf4d31c --- /dev/null +++ b/apps/docs/content/(array)/347-top-k-frequent-elements.mdx @@ -0,0 +1,51 @@ +--- +title: '347. Top K Frequent Elements' +description: Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order +sidebar: + label: 'Top K Frequent Elements' + badge: 'Medium' +--- + +Hash Table + +::::warning +Your algorithm's time complexity must be better than O(n log n), where n is the array's size. +:::: + +### 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. + +## Solution + +```js +/** + * @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); +}; +``` diff --git a/apps/docs/content/(array)/42-trapping-rain-water.mdx b/apps/docs/content/(array)/42-trapping-rain-water.mdx new file mode 100644 index 0000000..5638fd3 --- /dev/null +++ b/apps/docs/content/(array)/42-trapping-rain-water.mdx @@ -0,0 +1,36 @@ +--- +title: '42. Trapping Rain Water' +description: Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining +sidebar: + label: 'Trapping Rain Water' + badge: 'Hard' +--- + +Two Pointers + +### Example 1: +- Input: `height = [0,1,0,2,1,0,1,3,2,1,2,1]` +- Output: `6` +- Explanation: The above elevation map (black section) is represented by array `[0,1,0,2,1,0,1,3,2,1,2,1]`. In this case, `6` units of rain water (blue section) are being trapped. + +### Example 2: +- Input: `height = [4,2,0,3,2,5]` +- Output: `9` + +### Constraints: + +- `n == height.length` +- `1 <= n <= 2 * 10^4` +- `0 <= height[i] <= 10^5` + +## Solution + +```js +/** + * @param {number[]} height + * @return {number} + */ +var trap = function(height) { + +}; +``` diff --git a/apps/docs/content/(array)/49-group-anagrams.mdx b/apps/docs/content/(array)/49-group-anagrams.mdx new file mode 100644 index 0000000..75c52bc --- /dev/null +++ b/apps/docs/content/(array)/49-group-anagrams.mdx @@ -0,0 +1,51 @@ +--- +title: '49. Group Anagrams' +description: Given an array of strings strs, group the anagrams together. You can return the answer in any order +sidebar: + label: 'Group Anagrams' + badge: 'Medium' +--- + +Hash Table + +### Example 1: +- Input: `strs = ["eat","tea","tan","ate","nat","bat"]` +- Output: `[["bat"],["nat","tan"],["ate","eat","tea"]]` +- Explanation: There is no string in `strs` that can be rearranged to form `"bat"`. The strings `"nat"` and `"tan"` are anagrams as they can be rearranged to form each other. The strings `"ate"`, `"eat"`, and `"tea"` are anagrams as they can be rearranged to form each other. + +### Example 2: +- Input: `strs = [""]` +- Output: `[[""]]` + +### Example 3: +- Input: `strs = ["a"]` +- Output: `[["a"]]` + +### Constraints: + +- `1 <= strs.length <= 10^4` +- `0 <= strs[i].length <= 100` +- `strs[i]` consists of lowercase English letters. + +## Solution + +```js +/** + * @param {string[]} strs + * @return {string[][]} + */ +var groupAnagrams = function(strs) { + let sorted = strs.map(str => str.split("").sort().join("")); + let anagrams = {}; + + for (let i = 0; i < strs.length; i++){ + if(!anagrams[sorted[i]]){ + anagrams[sorted[i]] = [strs[i]] + }else{ + anagrams[sorted[i]].push(strs[i]) + } + } + + return Object.values(anagrams); +}; +``` diff --git a/apps/docs/content/(array)/560-subarray-sum-equals-k.mdx b/apps/docs/content/(array)/560-subarray-sum-equals-k.mdx new file mode 100644 index 0000000..2678d07 --- /dev/null +++ b/apps/docs/content/(array)/560-subarray-sum-equals-k.mdx @@ -0,0 +1,51 @@ +--- +title: '560. Subarray Sum Equals K' +description: Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k +sidebar: + label: 'Subarray Sum Equals K' + badge: 'Medium' +--- + +Prefix Sum + +### Example 1: +- Input: `nums = [1,1,1], k = 2` +- Output: `2` + +### Example 2: +- Input: `nums = [1,2,3], k = 3` +- Output: `2` + +### Constraints: + +- `1 <= nums.length <= 2 * 10^4` +- `-1000 <= nums[i] <= 1000` +- `-10^7 <= k <= 10^7` + +## Solution + +```js +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var subarraySum = function(nums, k) { + const map = new Map(); + map.set(0, 1); + + let sum = 0; + let count = 0; + + for (let n of nums){ + sum += n; + + if(map.has(sum - k)){ + count += map.get(sum - k); + } + + map.set(sum, (map.get(sum) || 0) + 1); + } + return count +}; +``` diff --git a/apps/docs/content/(array)/704-binary-search.mdx b/apps/docs/content/(array)/704-binary-search.mdx new file mode 100644 index 0000000..f92972b --- /dev/null +++ b/apps/docs/content/(array)/704-binary-search.mdx @@ -0,0 +1,56 @@ +--- +title: '704. Binary Search' +description: Given an array of integers nums which is sorted in ascending order, and an integer target, write a function to search target in nums. If target exists, then return its index. Otherwise, return -1 +sidebar: + label: 'Binary Search' + badge: 'Easy' +--- + +Binary Search + +::::warning +You must write an algorithm with O(log n) runtime complexity. +:::: + +### Example 1: +- Input: `nums = [-1,0,3,5,9,12], target = 9` +- Output: `4` +- Explanation: `9` exists in `nums` and its index is `4` + +### Example 2: +- Input: `nums = [-1,0,3,5,9,12], target = 2` +- Output: `-1` +- Explanation: `2` does not exist in `nums` so return `-1` + +### Constraints: + +- `1 <= nums.length <= 10^4` +- `-10^4 < nums[i], target < 10^4` +- All the integers in `nums` are unique. +- `nums` is sorted in ascending order. + +## Solution + +```js +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var search = function(nums, target) { + let left = 0; + let right = nums.length - 1; + + while(left <= right) { + const mid = left + Math.floor((right - left) / 2); + if (nums[mid] === target) { + return mid; + } else if(nums[mid] < target){ + left = mid + 1; + } else if (nums[mid] > target) { + right = mid - 1; + } + } + return -1; +}; +``` diff --git a/apps/docs/content/(array)/875-koko-eating-bananas.mdx b/apps/docs/content/(array)/875-koko-eating-bananas.mdx new file mode 100644 index 0000000..7682605 --- /dev/null +++ b/apps/docs/content/(array)/875-koko-eating-bananas.mdx @@ -0,0 +1,62 @@ +--- +title: '875. Koko Eating Bananas' +description: Koko loves to eat bananas. There are n piles of bananas, the i^th pile has piles[i] bananas. The guards have gone and will come back in h hours +sidebar: + label: 'Koko Eating Bananas' + badge: 'Medium' +--- + +Binary Search + +### Example 1: +- Input: `piles = [3,6,7,11], h = 8` +- Output: `4` + +### Example 2: +- Input: `piles = [30,11,23,4,20], h = 5` +- Output: `30` + +### Example 3: +- Input: `piles = [30,11,23,4,20], h = 6` +- Output: `23` + +### Constraints: + +- `1 <= piles.length <= 10^4` +- `piles.length <= h <= 10^9` +- `1 <= piles[i] <= 10^9` + +## Solution + +```js +/** + * @param {number[]} piles + * @param {number} h + * @return {number} + */ +var minEatingSpeed = function(piles, h) { + // Function to determine if K works for the H + function kWorks(k){ + let hours = 0; + for (let p of piles){ + hours += Math.ceil(p/k) + } + return hours <= h; + } + + // Setup Binary Search + let l = 1; + let r = Math.max(...piles); + + // Find the K value which works for H and consumes all bananas + while (l < r){ + const mid = Math.floor((l + r) / 2); + if (kWorks(mid)){ + r = mid; + }else{ + l = mid + 1; + } + } + return l; +}; +``` diff --git a/apps/docs/content/(array)/977-squares-of-a-sorted-array.mdx b/apps/docs/content/(array)/977-squares-of-a-sorted-array.mdx new file mode 100644 index 0000000..a79dd32 --- /dev/null +++ b/apps/docs/content/(array)/977-squares-of-a-sorted-array.mdx @@ -0,0 +1,55 @@ +--- +title: '977. Squares of a Sorted Array' +description: Given an integer array nums sorted in non-decreasing order, return an array of the squares of each number sorted in non-decreasing order +sidebar: + label: 'Squares of a Sorted Array' + badge: 'Easy' +--- + +Two Pointers + +::::warning +Squaring each element and sorting the new array is very trivial, could you find an O(n) solution using a different approach? +:::: + +### Example 1: +- Input: `nums = [-4,-1,0,3,10]` +- Output: `[0,1,9,16,100]` +- Explanation: After squaring, the array becomes `[16,1,0,9,100]`. After sorting, it becomes `[0,1,9,16,100]`. + +### Example 2: +- Input: `nums = [-7,-3,2,3,11]` +- Output: `[4,9,9,49,121]` + +### Constraints: + +- `1 <= nums.length <= 10^4` +- `-10^4 <= nums[i] <= 10^4` +- `nums` is sorted in non-decreasing order. + +## Solution + +```js +/** + * @param {number[]} nums + * @return {number[]} + */ +var sortedSquares = function(nums) { + let n = nums.length; + let ans = new Array(nums.length); + let left = 0, right = nums.length - 1; + + for (let i = n -1; i >= 0; i--){ + let square; + if(Math.abs(nums[left]) < Math.abs(nums[right])){ + square = nums[right]; + right--; + }else{ + square = nums[left]; + left++; + } + ans[i] = square*square; + } + return ans; +}; +``` diff --git a/apps/docs/content/(hash-table)/1832-check-if-the-sentence-is-pangram.mdx b/apps/docs/content/(hash-table)/1832-check-if-the-sentence-is-pangram.mdx new file mode 100644 index 0000000..e669c06 --- /dev/null +++ b/apps/docs/content/(hash-table)/1832-check-if-the-sentence-is-pangram.mdx @@ -0,0 +1,41 @@ +--- +title: '1832. Check if the Sentence Is Pangram' +description: A pangram is a sentence where every letter of the English alphabet appears at least once +sidebar: + label: 'Check if the Sentence Is Pangram' + badge: 'Easy' +--- + +Hash Table + +### Example 1: +- Input: `sentence = "thequickbrownfoxjumpsoverthelazydog"` +- Output: `true` +- Explanation: `sentence` contains at least one of every letter of the English alphabet. + +### Example 2: +- Input: `sentence = "leetcode"` +- Output: `false` + +### Constraints: + +- `1 <= sentence.length <= 1000` +- `sentence` consists of lowercase English letters. + +## Solution + +```js +/** + * @param {string} sentence + * @return {boolean} + */ +var checkIfPangram = function(sentence) { + const freq = {}; + for (let c of sentence) freq[c] = (freq[c] || 0) + 1; + + if (Object.keys(freq).length === 26){ + return true; + } + return false; +}; +``` diff --git a/apps/docs/content/(hash-table)/242-valid-anagram.mdx b/apps/docs/content/(hash-table)/242-valid-anagram.mdx new file mode 100644 index 0000000..dff1203 --- /dev/null +++ b/apps/docs/content/(hash-table)/242-valid-anagram.mdx @@ -0,0 +1,48 @@ +--- +title: '242. Valid Anagram' +description: Given two strings s and t, return true if t is an anagram of s, and false otherwise +sidebar: + label: 'Valid Anagram' + badge: 'Easy' +--- + +Hash Table + +::::warning +What if the inputs contain Unicode characters? How would you adapt your solution to such a case? +:::: + +### Example 1: +- Input: `s = "anagram", t = "nagaram"` +- Output: `true` + +### Example 2: +- Input: `s = "rat", t = "car"` +- Output: `false` + +### Constraints: + +- `1 <= s.length, t.length <= 5 * 10^4` +- `s` and `t` consist of lowercase English letters. + +## Solution + +```js +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +var isAnagram = function(s, t) { + let freq = {}; + for (let c of s) freq[c] = (freq[c] || 0) + 1; + + for (let c of t) { + if(!freq[c] || freq[c] === 0){ + return false; + } + freq[c] = freq[c] - 1; + } + return true; +}; +``` diff --git a/apps/docs/content/(hash-table)/387-first-unique-character-in-a-string.mdx b/apps/docs/content/(hash-table)/387-first-unique-character-in-a-string.mdx new file mode 100644 index 0000000..065a16c --- /dev/null +++ b/apps/docs/content/(hash-table)/387-first-unique-character-in-a-string.mdx @@ -0,0 +1,47 @@ +--- +title: '387. First Unique Character in a String' +description: Given a string s, find the first non-repeating character in it and return its index. If it does not exist, return -1 +sidebar: + label: 'First Unique Character in a String' + badge: 'Easy' +--- + +Hash Table + +### 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. + +## Solution + +```js +/** + * @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; +}; +``` diff --git a/apps/docs/content/(hash-table)/451-sort-characters-by-frequency.mdx b/apps/docs/content/(hash-table)/451-sort-characters-by-frequency.mdx new file mode 100644 index 0000000..a0415a1 --- /dev/null +++ b/apps/docs/content/(hash-table)/451-sort-characters-by-frequency.mdx @@ -0,0 +1,49 @@ +--- +title: '451. Sort Characters By Frequency' +description: 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 +sidebar: + label: 'Sort Characters By Frequency' + badge: 'Medium' +--- + +Hash Table + +### 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. + +## Solution + +```js +/** + * @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(""); +}; +``` diff --git a/apps/docs/content/(two-pointers)/125-valid-palindrome.mdx b/apps/docs/content/(two-pointers)/125-valid-palindrome.mdx new file mode 100644 index 0000000..027d09f --- /dev/null +++ b/apps/docs/content/(two-pointers)/125-valid-palindrome.mdx @@ -0,0 +1,51 @@ +--- +title: '125. Valid Palindrome' +description: A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers +sidebar: + label: 'Valid Palindrome' + badge: 'Easy' +--- + +Two Pointers + +### Example 1: +- Input: `s = "A man, a plan, a canal: Panama"` +- Output: `true` +- Explanation: `"amanaplanacanalpanama"` is a palindrome. + +### Example 2: +- Input: `s = "race a car"` +- Output: `false` +- Explanation: `"raceacar"` is not a palindrome. + +### Example 3: +- Input: `s = " "` +- Output: `true` +- Explanation: `s` is an empty string `""` after removing non-alphanumeric characters. Since an empty string reads the same forward and backward, it is a palindrome. + +### Constraints: + +- `1 <= s.length <= 2 * 10^5` +- `s` consists only of printable ASCII characters. + +## Solution + +```js +/** + * @param {string} s + * @return {boolean} + */ +var isPalindrome = function(s) { + let normal = s.replace(/[^a-zA-Z0-9]/g, "").toLowerCase() + let i = 0, j = normal.length - 1; + + while (i < j) { + if(normal[i] !== normal[j]) { + return false; + } + i++; + j--; + } + return true; +}; +``` diff --git a/apps/docs/content/(two-pointers)/344-reverse-string.mdx b/apps/docs/content/(two-pointers)/344-reverse-string.mdx new file mode 100644 index 0000000..9e94efe --- /dev/null +++ b/apps/docs/content/(two-pointers)/344-reverse-string.mdx @@ -0,0 +1,45 @@ +--- +title: '344. Reverse String' +description: Write a function that reverses a string. The input string is given as an array of characters s +sidebar: + label: 'Reverse String' + badge: 'Easy' +--- + +Two Pointers + +:::warning +You must do this by modifying the input array in-place with O(1) extra memory. +::: + +### Example 1: +- Input: `s = ["h","e","l","l","o"]` +- Output: `["o","l","l","e","h"]` + +### Example 2: +- Input: `s = ["H","a","n","n","a","h"]` +- Output: `["h","a","n","n","a","H"]` + +### Constraints: + +- `1 <= s.length <= 10^5` +- `s[i]` is a printable ascii character. + +## Solution + +```js +/** + * @param {character[]} s + * @return {void} Do not return anything, modify s in-place instead. + */ +var reverseString = function(s) { + let i = 0; + let j = s.length - 1; + + while (i < j) { + [s[i], s[j]] = [s[j], s[i]]; + j--; + i++; + } +}; +``` diff --git a/apps/docs/content/(two-pointers)/392-is-subsequence.mdx b/apps/docs/content/(two-pointers)/392-is-subsequence.mdx new file mode 100644 index 0000000..36c8b59 --- /dev/null +++ b/apps/docs/content/(two-pointers)/392-is-subsequence.mdx @@ -0,0 +1,44 @@ +--- +title: '392. Is Subsequence' +description: Given two strings s and t, return true if s is a subsequence of t, or false otherwise +sidebar: + label: 'Is Subsequence' + badge: 'Easy' +--- + +Two Pointers + +::::warning +Suppose there are lots of incoming s, say s1, s2, ..., sk where k >= 10^9, and you want to check one by one to see if t has its subsequence. In this scenario, how would you change your code? +:::: + +### Example 1: +- Input: `s = "abc", t = "ahbgdc"` +- Output: `true` + +### Example 2: +- Input: `s = "axc", t = "ahbgdc"` +- Output: `false` + +### Constraints: + +- `0 <= s.length <= 100` +- `0 <= t.length <= 10^4` +- `s` and `t` consist only of lowercase English letters. + +## Solution + +```py +class Solution: + def isSubsequence(self, s: str, t: str) -> bool: + if len(s) > len(t): + return False + + i, j = 0, 0 + while i < len(s) and j < len(t): + if s[i] == t[j]: + i += 1 + j += 1 + + return i == len(s) +``` diff --git a/apps/docs/content/index.mdx b/apps/docs/content/index.mdx new file mode 100644 index 0000000..7db9701 --- /dev/null +++ b/apps/docs/content/index.mdx @@ -0,0 +1,12 @@ +--- +title: Introduction +description: Welcome to your new Blume docs. +--- + +## Getting Started + +![Dependency Map](../public/dependency-spine.svg) + +Welcome to **Blume** — markdown-first docs powered by Astro and Vite. + +Edit `docs/index.mdx` to get started, then run `blume dev`. diff --git a/apps/docs/content/progress.mdx b/apps/docs/content/progress.mdx new file mode 100644 index 0000000..fa87d8f --- /dev/null +++ b/apps/docs/content/progress.mdx @@ -0,0 +1,9 @@ +--- +title: Progress +description: Live SRS campaign dashboard — phases, ladder, review queue, gates, and recent attempts, fetched from the SRS Worker. +--- + +Live view of the 56-day campaign. Everything below is fetched client-side +from the SRS Worker, so it is always current — no rebuild required. + + diff --git a/apps/docs/islands/ProgressDashboard.tsx b/apps/docs/islands/ProgressDashboard.tsx new file mode 100644 index 0000000..1fb3e78 --- /dev/null +++ b/apps/docs/islands/ProgressDashboard.tsx @@ -0,0 +1,351 @@ +/** + * Progress dashboard island — the expanded, always-current version of the + * daily email footer. Rendered on /progress; fetches campaign state from the + * SRS Worker at page load, entirely client-side, so `blume build` never + * depends on the API being up. API_BASE is a placeholder stamped in after the + * Worker deploys — do not inline it anywhere else. + * + * Invariants: the component never throws on malformed API data (a shape guard + * downgrades to the error state), and the first frame is always the loading + * state so server and client render identically. + */ +import { useEffect, useState, type CSSProperties } from "react"; + +export const client = "load"; + +const API_BASE = "https://srs-api.prdlk.workers.dev"; + +// ── /api/stats response shape ──────────────────────────────────── + +const STAGES = ["new", "+2", "+5", "+10", "retired"] as const; + +type Stage = (typeof STAGES)[number]; + +interface Stats { + generated: string; + campaign: { day: number; week: number; start: string; days: number }; + phases: { + milestone: number; + name: string; + core_done: number; + core_total: number; + optional_done: number; + optional_total: number; + deferred_done: number; + deferred_total: number; + }[]; + ladder: Record; + gates: { + week: number; + issue: number | null; + pass_rate: number | null; + closed_on: string | null; + }[]; + streak: number; + queue: { date: string; due: number }[]; + recent: { date: string; attempts: number; passes: number }[]; +} + +function isStats(value: unknown): value is Stats { + if (typeof value !== "object" || value === null) return false; + const v = value as Record; + return ( + typeof v.campaign === "object" && + v.campaign !== null && + typeof v.ladder === "object" && + v.ladder !== null && + Array.isArray(v.phases) && + Array.isArray(v.gates) && + Array.isArray(v.queue) && + Array.isArray(v.recent) && + typeof v.streak === "number" + ); +} + +// ── formatting ─────────────────────────────────────────────────── + +/** Legacy gates stored integer percent; the Worker may emit a 0–1 fraction. */ +function percent(rate: number): string { + return `${Math.round(rate <= 1 ? rate * 100 : rate)}%`; +} + +/** "2026-08-24" → "Mon 24" without timezone drift. */ +function dayLabel(iso: string): string { + const d = new Date(`${iso}T00:00:00`); + const weekday = d.toLocaleDateString("en-US", { weekday: "short" }); + return `${weekday} ${iso.slice(8)}`; +} + +// ── shared styles (theme tokens only — no hand-rolled palette) ─── + +const card: CSSProperties = { + border: "1px solid var(--blume-border)", + borderRadius: "var(--blume-radius)", + padding: "0.75rem 1rem", + marginBottom: "1rem", +}; + +const muted: CSSProperties = { + color: "var(--blume-muted-foreground)", + fontSize: "0.85em", +}; + +const heading: CSSProperties = { + fontWeight: 600, + marginBottom: "0.5rem", +}; + +function Bar({ done, total }: { done: number; total: number }) { + const ratio = total > 0 ? Math.min(done / total, 1) : 0; + return ( + + + + ); +} + +// ── sections ───────────────────────────────────────────────────── + +function Header({ stats }: { stats: Stats }) { + const { campaign, streak } = stats; + return ( +
+ + + Day {campaign.day}/{campaign.days} + + + Week {campaign.week} + + Streak: {streak} day{streak === 1 ? "" : "s"} + + started {campaign.start} +
+ ); +} + +function Phases({ stats }: { stats: Stats }) { + return ( +
+
Phases
+ + + {stats.phases.map((p) => ( + + + + + + ))} + +
{p.name} + {" "} + + core {p.core_done}/{p.core_total} + + + + optional {p.optional_done}/{p.optional_total} + {p.deferred_total > 0 && + ` · deferred ${p.deferred_done}/${p.deferred_total}`} + +
+
+ ); +} + +function Ladder({ stats }: { stats: Stats }) { + return ( +
+
SRS ladder
+
+ {STAGES.map((stage) => ( + + {stage}{" "} + {stats.ladder[stage] ?? 0} + + ))} +
+
+ ); +} + +function Queue({ stats }: { stats: Stats }) { + const max = Math.max(1, ...stats.queue.map((q) => q.due)); + return ( +
+
Review queue — next 14 days
+ + + {stats.queue.map((q) => ( + + + + + + ))} + +
+ {dayLabel(q.date)} + + + {q.due}
+
+ ); +} + +function Gates({ stats }: { stats: Stats }) { + return ( +
+
Gate log
+ {stats.gates.length === 0 ? ( + No gates yet. + ) : ( + + + + {["Week", "Issue", "Pass rate", "Closed"].map((h) => ( + + ))} + + + + {stats.gates.map((g) => ( + + + + + + + ))} + +
+ {h} +
{g.week} + {g.issue === null ? ( + + ) : ( + + #{g.issue} + + )} + + {g.pass_rate === null ? ( + open + ) : ( + percent(g.pass_rate) + )} + + {g.closed_on ?? } +
+ )} +
+ ); +} + +function Recent({ stats }: { stats: Stats }) { + return ( +
+
Last 7 days
+
+ {stats.recent.map((r) => ( + + {dayLabel(r.date)} + {r.passes} + /{r.attempts} + + ))} +
+
passes / attempts
+
+ ); +} + +// ── dashboard ──────────────────────────────────────────────────── + +type Load = + | { phase: "loading" } + | { phase: "error" } + | { phase: "ready"; stats: Stats }; + +export default function ProgressDashboard() { + const [load, setLoad] = useState({ phase: "loading" }); + + useEffect(() => { + const controller = new AbortController(); + fetch(`${API_BASE}/api/stats`, { signal: controller.signal }) + .then((res) => { + if (!res.ok) throw new Error(`HTTP ${res.status}`); + return res.json(); + }) + .then((body: unknown) => { + setLoad(isStats(body) ? { phase: "ready", stats: body } : { phase: "error" }); + }) + .catch(() => { + if (!controller.signal.aborted) setLoad({ phase: "error" }); + }); + return () => controller.abort(); + }, []); + + if (load.phase === "loading") { + return

Loading progress…

; + } + if (load.phase === "error") { + return ( +

+ API unreachable — stats are served live from the SRS Worker and it did + not respond. +

+ ); + } + + const { stats } = load; + return ( +
+
+ + + + + +

Generated {stats.generated}

+
+ ); +} diff --git a/apps/docs/public/dependency-spine.html b/apps/docs/public/dependency-spine.html new file mode 100644 index 0000000..fab07ab --- /dev/null +++ b/apps/docs/public/dependency-spine.html @@ -0,0 +1,305 @@ + + + + + + LeetCode Dependency Spine + + + + +
+

prdlk / leetcode · dependency spine

+

How the 24 topics build on each other

+ + + LeetCode topic dependency spine + Dependency graph of 24 LeetCode study topics across five phases, showing which topics build on which, with Tree DFS and 1-D dynamic programming as the two central hubs. + + + + + + + + + + + + PHASE I — LINEAR STRUCTURES + + + + PHASE III — HIERARCHICAL + + + + PHASE II — NODAL & GRID + + + + PHASES IV–V — RELATIONAL & DECISION-SPACE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 05 + Binary Search + + + + + + 03 + Two Pointers + + + + + + 04 + Sliding Window + + + + + + 06 + Stack + + + + + + 07 + Monotonic Stack + + + + + + 01 + Hash Lookup + + + + + + 02 + Prefix Sum + + + + + + 11 + Tree DFS + + + + + + 13 + Binary Search Tree + + + + + + 14 + Heap + priority queue + + + + + + 15 + Trie + + + + + + 12 + Tree BFS + + + + + + 08 + Linked List + + + + + + 09 + Hybrid Structures + + + + + + 10 + Matrix Index Math + + + + + + 16 + Graph DFS + + + + + + 18 + Topological Sort + + + + + + 19 + Union-Find + + + + + + 20 + Backtracking + + + + + + 21 + 1-D DP + dynamic programming + + + + + + 22 + Multi-D / Grid DP + + + + + + 17 + Graph BFS + + + + + + 23 + Greedy + + + + + + 24 + Intervals + + + + LEGEND + + + ENTRY — NO PREREQS + + + TOPIC + + + FOCAL HUB + + + BUILDS ON + + + PHASE ZONE + +
+ + diff --git a/apps/docs/public/dependency-spine.svg b/apps/docs/public/dependency-spine.svg new file mode 100644 index 0000000..1eb30df --- /dev/null +++ b/apps/docs/public/dependency-spine.svg @@ -0,0 +1,244 @@ + + + LeetCode topic dependency spine + Dependency graph of 24 LeetCode study topics across five phases, showing which topics build on which, with Tree DFS and 1-D dynamic programming as the two central hubs. + + + + + + + + + + + + + PHASE I — LINEAR STRUCTURES + + + + PHASE III — HIERARCHICAL + + + + PHASE II — NODAL & GRID + + + + PHASES IV–V — RELATIONAL & DECISION-SPACE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 05 + Binary Search + + + + + + 03 + Two Pointers + + + + + + 04 + Sliding Window + + + + + + 06 + Stack + + + + + + 07 + Monotonic Stack + + + + + + 01 + Hash Lookup + + + + + + 02 + Prefix Sum + + + + + + 11 + Tree DFS + + + + + + 13 + Binary Search Tree + + + + + + 14 + Heap + priority queue + + + + + + 15 + Trie + + + + + + 12 + Tree BFS + + + + + + 08 + Linked List + + + + + + 09 + Hybrid Structures + + + + + + 10 + Matrix Index Math + + + + + + 16 + Graph DFS + + + + + + 18 + Topological Sort + + + + + + 19 + Union-Find + + + + + + 20 + Backtracking + + + + + + 21 + 1-D DP + dynamic programming + + + + + + 22 + Multi-D / Grid DP + + + + + + 17 + Graph BFS + + + + + + 23 + Greedy + + + + + + 24 + Intervals + + + + LEGEND + + + ENTRY — NO PREREQS + + + TOPIC + + + FOCAL HUB + + + BUILDS ON + + + PHASE ZONE +