mirror of
https://github.com/prdlk/leetcode.git
synced 2026-11-03 05:27:36 +00:00
chore: clean up content phase organization
This commit is contained in:
1 parent
403a2d7f23
commit
bf0ac34a43
138 files changed
+1436
-368
No files matched your search
+60
@@ -0,0 +1,60 @@
|
||||
---
|
||||
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'
|
||||
---
|
||||
|
||||
<Badge variant="accent">Array</Badge>
|
||||
|
||||
### 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`
|
||||
|
||||
## Approach
|
||||
|
||||
::::warning
|
||||
The diagram traces the code below literally. That code does not run: `curr` and `ans` are never initialised, so the first `curr > left` test raises `NameError`, and `left` holds a price rather than an index, so `prices[left]` indexes by value.
|
||||
::::
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S(["maxProfit(prices)"]) --> I["left = min(prices)"]
|
||||
I --> F{"more right in range(len(prices))?"}
|
||||
F -- no --> E(["return ans"])
|
||||
F -- yes --> W{"curr > left?"}
|
||||
W -- yes --> P["curr -= prices[left]; left += 1"]
|
||||
P --> W
|
||||
W -- no --> M["ans = max(ans, curr)"]
|
||||
M --> F
|
||||
```
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Explanation
|
||||
|
||||
<YouTube id="1pkOgXD63yU" title="Sliding Window: Best Time to Buy and Sell Stock - Leetcode 121 - Python" />
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: '3. Longest Substring Without Repeating Characters'
|
||||
description: Given a string s, find the length of the longest substring without duplicate characters
|
||||
sidebar:
|
||||
label: 'Longest Substring Without Repeating Characters'
|
||||
badge: 'Medium'
|
||||
---
|
||||
|
||||
<Badge variant="accent">Hash Table</Badge>
|
||||
|
||||
### Example 1:
|
||||
- Input: `s = "abcabcbb"`
|
||||
- Output: `3`
|
||||
- Explanation: The answer is "abc", with the length of `3`. Note that "bca" and "cab" are also correct answers.
|
||||
|
||||
### Example 2:
|
||||
- Input: `s = "bbbbb"`
|
||||
- Output: `1`
|
||||
- Explanation: The answer is "b", with the length of `1`.
|
||||
|
||||
### Example 3:
|
||||
- Input: `s = "pwwkew"`
|
||||
- Output: `3`
|
||||
- Explanation: The answer is "wke", with the length of `3`. Notice that the answer must be a substring, "pwke" is a subsequence and not a substring.
|
||||
|
||||
### Constraints:
|
||||
|
||||
- `0 <= s.length <= 10^5`
|
||||
- `s` consists of English letters, digits, symbols and spaces.
|
||||
|
||||
## Approach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S(["lengthOfLongestSubstring(s)"]) --> I["left = 0, ans = 0, window = set()"]
|
||||
I --> L{"more (right, c) in s?"}
|
||||
L -- no --> E(["return ans"])
|
||||
L -- yes --> W{"c already in window?"}
|
||||
W -- yes --> P["window.remove(s[left]); left += 1 — shrink until c is free"]
|
||||
P --> W
|
||||
W -- no --> A["window.add(c)"]
|
||||
A --> M["ans = max(ans, right - left + 1)"]
|
||||
M --> L
|
||||
```
|
||||
|
||||
## Solution
|
||||
|
||||
```py
|
||||
class Solution:
|
||||
def lengthOfLongestSubstring(self, s: str) -> int:
|
||||
left = 0
|
||||
ans = 0
|
||||
window = set()
|
||||
for right, c in enumerate(s):
|
||||
while c in window:
|
||||
window.remove(s[left])
|
||||
left += 1
|
||||
window.add(c)
|
||||
ans = max(ans, right - left + 1)
|
||||
|
||||
return ans
|
||||
```
|
||||
|
||||
## Explanation
|
||||
|
||||
<YouTube id="wiGpQwVHdE0" title="Longest Substring Without Repeating Characters - Leetcode 3 - Python" />
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: '424. Longest Repeating Character Replacement'
|
||||
description: You are given a string s and an integer k. You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k times
|
||||
sidebar:
|
||||
label: 'Longest Repeating Character Replacement'
|
||||
badge: 'Medium'
|
||||
---
|
||||
|
||||
<Badge variant="accent">Hash Table</Badge>
|
||||
|
||||
### Example 1:
|
||||
- Input: `s = "ABAB", k = 2`
|
||||
- Output: `4`
|
||||
- Explanation: Replace the two 'A's with two 'B's or vice versa.
|
||||
|
||||
### Example 2:
|
||||
- Input: `s = "AABABBA", k = 1`
|
||||
- Output: `4`
|
||||
- Explanation: Replace the one 'A' in the middle with 'B' and form "AABBBBA". The substring "BBBB" has the longest repeating letters, which is `4`. There may exists other ways to achieve this answer too.
|
||||
|
||||
### Constraints:
|
||||
|
||||
- `1 <= s.length <= 10^5`
|
||||
- `s` consists of only uppercase English letters.
|
||||
- `0 <= k <= s.length`
|
||||
|
||||
## Approach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S(["characterReplacement(s, k)"]) --> I["count = {}, res = 0, l = 0, maxF = 0"]
|
||||
I --> L{"more (r, c) in s?"}
|
||||
L -- no --> E(["return res"])
|
||||
L -- yes --> A["count[c] += 1; maxF = max(maxF, count[c])"]
|
||||
A --> W{"(r - l + 1) - maxF > k? — too many chars to replace"}
|
||||
W -- yes --> P["count[s[l]] -= 1; l += 1 — shrink from the left"]
|
||||
P --> W
|
||||
W -- no --> M["res = max(res, r - l + 1)"]
|
||||
M --> L
|
||||
```
|
||||
|
||||
## Solution
|
||||
|
||||
```py
|
||||
class Solution:
|
||||
def characterReplacement(self, s: str, k: int) -> int:
|
||||
count = {}
|
||||
res = 0
|
||||
|
||||
l = 0
|
||||
maxF = 0
|
||||
for r, c in enumerate(s):
|
||||
count[c] = 1 + count.get(c, 0)
|
||||
maxF = max(maxF, count[c])
|
||||
|
||||
while (r - l + 1) - maxF > k:
|
||||
count[s[l]] -= 1
|
||||
l += 1
|
||||
|
||||
res = max(res, r - l + 1)
|
||||
return res
|
||||
```
|
||||
|
||||
## Explanation
|
||||
|
||||
<YouTube id="gqXU1UyA8pk" title="Longest Repeating Character Replacement - Leetcode 424 - Python" />
|
||||
@@ -0,0 +1,73 @@
|
||||
---
|
||||
title: '567. Permutation in String'
|
||||
description: Given two strings s1 and s2, return true if s2 contains a permutation of s1, or false otherwise
|
||||
sidebar:
|
||||
label: 'Permutation in String'
|
||||
badge: 'Medium'
|
||||
---
|
||||
|
||||
<Badge variant="accent">Hash Table</Badge>
|
||||
|
||||
### Example 1:
|
||||
- Input: `s1 = "ab", s2 = "eidbaooo"`
|
||||
- Output: `true`
|
||||
- Explanation: `s2` contains one permutation of `s1` ("ba").
|
||||
|
||||
### Example 2:
|
||||
- Input: `s1 = "ab", s2 = "eidboaoo"`
|
||||
- Output: `false`
|
||||
|
||||
### Constraints:
|
||||
|
||||
- `1 <= s1.length, s2.length <= 10^4`
|
||||
- `s1` and `s2` consist of lowercase English letters.
|
||||
|
||||
## Approach
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
S(["checkInclusion(s1, s2)"]) --> G{"k = len(s1) > len(s2)?"}
|
||||
G -- yes --> X(["return False"])
|
||||
G -- no --> I["need = Counter(s1), window = Counter()"]
|
||||
I --> L{"more (right, c) in s2?"}
|
||||
L -- no --> E(["return False"])
|
||||
L -- yes --> A["window[c] += 1"]
|
||||
A --> B{"right >= k? — window is now longer than k"}
|
||||
B -- yes --> C["drop s2[right - k] from window, deleting the key at 0"]
|
||||
B -- no --> Q
|
||||
C --> Q{"window == need?"}
|
||||
Q -- yes --> R(["return True"])
|
||||
Q -- no --> L
|
||||
```
|
||||
|
||||
## Solution
|
||||
|
||||
```py
|
||||
from collections import Counter
|
||||
|
||||
|
||||
class Solution:
|
||||
def checkInclusion(self, s1: str, s2: str) -> bool:
|
||||
k = len(s1)
|
||||
if k > len(s2):
|
||||
return False
|
||||
|
||||
need = Counter(s1)
|
||||
window = Counter()
|
||||
|
||||
for right, c in enumerate(s2):
|
||||
window[c] += 1
|
||||
if right >= k:
|
||||
left_char = s2[right - k]
|
||||
window[left_char] -= 1
|
||||
if window[left_char] == 0:
|
||||
del window[left_char]
|
||||
if window == need:
|
||||
return True
|
||||
|
||||
return False
|
||||
```
|
||||
|
||||
## Explanation
|
||||
|
||||
<YouTube id="UbyhOgBN834" title="Permutation in String - Leetcode 567 - Python" />
|
||||
@@ -0,0 +1,104 @@
|
||||
---
|
||||
title: Sliding Window
|
||||
description: 'Sliding window is a specialized two-pointer family where the pointers define a contiguous interval and you maintain information about that entire interval as it moves.'
|
||||
hidden: true
|
||||
---
|
||||
|
||||
:::warning
|
||||
This is the family where invariants matter the most
|
||||
:::
|
||||
|
||||
## What Makes Sliding Window Different?
|
||||
|
||||
Many problems have two moving boundaries. That alone does not make them sliding window problems.
|
||||
|
||||
A problem belongs to this family when:
|
||||
|
||||
- the answer depends on the subarray or substring between left and right
|
||||
- you can update the window state incrementally as elements enter or leave
|
||||
- you maintain a condition that tells you whether the window is valid
|
||||
|
||||
## What is an Invariant?
|
||||
|
||||
|
||||
An invariant is a statement that stays true before and after every iteration.
|
||||
|
||||
For sliding window, the invariant often looks like one of these:
|
||||
|
||||
- "the current window is valid"
|
||||
- "the current window contains no duplicates"
|
||||
- "the current window sum is at most the target"
|
||||
- "the frequency map matches the characters currently inside the window"
|
||||
|
||||
The invariant gives the loop its structure:
|
||||
|
||||
- expand the window by moving right
|
||||
- update the window state
|
||||
- if the invariant breaks, shrink from the left until it holds again
|
||||
- update the answer only when you know the invariant is satisfied
|
||||
|
||||
|
||||
## Why Invariants Matter
|
||||
|
||||
Without an invariant, shrinking the window becomes arbitrary. You no longer know:
|
||||
|
||||
- when the window is valid
|
||||
- when to update the answer
|
||||
- why the left pointer should stop moving
|
||||
- The invariant is the reason the algorithm is correct.
|
||||
|
||||
## The Main Subtypes
|
||||
|
||||
### 1. Fixed-size windows
|
||||
|
||||
:::tip
|
||||
The window size never changes. The main task is updating the window state efficiently when one element enters and one leaves.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
### 2. Flexible-size windows with a validity rule
|
||||
|
||||
:::tip
|
||||
Here the window expands until invalid, then shrinks until valid again.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
|
||||
### 3. Frequency-tracking windows
|
||||
|
||||
:::tip
|
||||
The difficulty comes from keeping the bookkeeping correct as characters enter and leave.
|
||||
:::
|
||||
|
||||

|
||||
|
||||
## How Sliding Window Differs From Other Two-Pointer Families
|
||||
|
||||
Compare it with Container With Most Water:
|
||||
|
||||
- In sliding window, the interval itself has meaning.
|
||||
- In container, the interval is just the remaining search space.
|
||||
|
||||
Compare it with Remove Duplicates:
|
||||
|
||||
- In sliding window, both pointers describe a live window.
|
||||
- In compaction, the left part of the array is already the answer prefix.
|
||||
|
||||
## A Practical Template
|
||||
|
||||
A common variable-size sliding window has this shape:
|
||||
|
||||
1. Add the new rightmost element.
|
||||
2. Update the window state.
|
||||
3. While the invariant is broken, remove elements from the left.
|
||||
4. Once the invariant is restored, update the answer.
|
||||
|
||||
The exact data structure changes from problem to problem, but the logic stays the same.
|
||||
|
||||
As you work through this section, keep asking:
|
||||
|
||||
:::warning
|
||||
What invariant does my window maintain, and at what moment is it safe to update the answer?
|
||||
:::
|
||||
@@ -0,0 +1,3 @@
|
||||
import { defineMeta } from "blume";
|
||||
|
||||
export default defineMeta({ title: "Sliding Window", order: 4, icon: "app-window", display: "group" });
|
||||
Reference in new issue
Block a user