Skip to content

2025/05/16 #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
May 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
79 changes: 79 additions & 0 deletions Hard/895 Maximum Frequency Stack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 895. Maximum Frequency Stack

## Intuition

The problem requires us to implement a stack-like data structure that can track the frequency of elements and pop the most frequent element. When multiple elements have the same frequency, we need to pop the one that was pushed most recently. The key insight is to maintain a frequency map and a stack of stacks, where each inner stack contains elements of the same frequency.

## Approach

1. Use a `freqMap` to track the frequency of each element
2. Use a `freqStack` which is a 2D slice where:
- Each inner slice represents elements of the same frequency
- The index of the inner slice represents the frequency level
- Elements in the same inner slice maintain their push order
3. For Push operation:
- If element is new or has frequency -1, add it to frequency level 0
- Otherwise, increment its frequency and add it to the corresponding level
4. For Pop operation:
- Remove the last element from the highest frequency level
- Decrement its frequency in the map
- Remove the frequency level if it becomes empty

## Complexity

- Time complexity: O(1)
- Space complexity: O(n)

## Keywords

- Stack
- Hash Map

## Code

```go
type FreqStack struct {
freqMap map[int]int
freqStack [][]int
}


func Constructor() FreqStack {
f := FreqStack{
freqMap: make(map[int]int),
freqStack: make([][]int, 0),
}
f.freqStack = append(f.freqStack, make([]int, 0))
return f
}


func (f *FreqStack) Push(val int) {
if level, found := f.freqMap[val]; !found || level == -1 {
f.freqStack[0], f.freqMap[val] = append(f.freqStack[0], val), 0
} else {
if len(f.freqStack) - 1 == level {
f.freqStack = append(f.freqStack, make([]int, 0))
}
f.freqStack[level + 1], f.freqMap[val] = append(f.freqStack[level + 1], val), level + 1
}
}


func (f *FreqStack) Pop() int {
tgt := f.freqStack[len(f.freqStack) - 1][len(f.freqStack[len(f.freqStack) - 1]) - 1]
f.freqStack[len(f.freqStack) - 1], f.freqMap[tgt] = f.freqStack[len(f.freqStack) - 1][: len(f.freqStack[len(f.freqStack) - 1]) - 1], f.freqMap[tgt] - 1
if len(f.freqStack[len(f.freqStack) - 1]) == 0 {
f.freqStack = f.freqStack[: len(f.freqStack) - 1]
}
return tgt
}


/**
* Your FreqStack object will be instantiated and called as such:
* obj := Constructor();
* obj.Push(val);
* param_2 := obj.Pop();
*/
```
62 changes: 62 additions & 0 deletions Medium/1209 Remove All Adjacent Duplicates in String II.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 1209. Remove All Adjacent Duplicates in String II

## Intuition

The problem requires us to remove k adjacent duplicate characters from a string. We can use a stack-based approach where we keep track of both the character and its count. When we encounter k consecutive same characters, we remove them from the stack.

## Approach

1. Create a stack to store pairs of (character, count)
2. Iterate through each character in the string:
- If stack is empty, push the character with count 1
- If current character matches the top of stack:
- Increment the count
- If count reaches k, pop the element from stack
- If current character is different, push it with count 1
3. Finally, reconstruct the string from the stack by repeating each character according to its count

## Complexity

- Time complexity: O(n)
- Space complexity: O(n)

## Keywords

- Stack
- String Manipulation

## Code

```go
func removeDuplicates(s string, k int) string {
type unit struct {
char rune
cnt int
}

st := make([]unit, 0)

for _, char := range s {
if len(st) == 0 {
st = append(st, unit{char: char, cnt: 1})
continue
}
if st[len(st) - 1].char == char {
st[len(st) - 1].cnt += 1
if st[len(st) - 1].cnt == k {
st = st[:len(st) - 1]
}
continue
}
st = append(st, unit{char: char, cnt: 1})
}

ret := ""
for _, u := range st {
for i := 0; i < u.cnt; i += 1 {
ret += string(u.char)
}
}
return ret
}
```
57 changes: 57 additions & 0 deletions Medium/316. Remove Duplicate Letters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 316. Remove Duplicate Letters

## Intuition

The problem requires us to remove duplicate letters from a string while maintaining the lexicographically smallest possible result. We need to ensure that:

1. Each character appears only once in the result
2. The relative order of characters is preserved
3. The result is lexicographically smallest among all possible results

## Approach

1. First, we create a map `lastSeen` to record the last occurrence of each character in the string
2. We use a stack (`st`) to build our result and a set (`seen`) to track characters we've already included
3. For each character in the string:
- If we haven't seen it before, we try to add it to our result
- Before adding, we check if we can remove characters from the stack that are:
- Greater than the current character (to maintain lexicographical order)
- Will appear again later in the string (using lastSeen map)
4. Finally, we convert the stack to a string and return it

## Complexity

- Time complexity: O(n)
- Space complexity: O(n)

## Keywords

- Stack
- Greedy
- String
- Hash Map
- Lexicographical Order

## Code

```go
func removeDuplicateLetters(s string) string {
lastSeen := make(map[rune]int)
for i, c := range s {
lastSeen[c] = i
}

st, seen := make([]rune, 0), make(map[rune]bool)
for i, c := range s {
if !seen[c] {
for len(st) > 0 && c < st[len(st) - 1] && i < lastSeen[st[len(st) - 1]] {
delete(seen, st[len(st) - 1])
st = st[: len(st) - 1]
}
seen[c], st = true, append(st, c)
}
}

return string(st)
}
```
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
| 236 | Lowest Common Ancestor of a Binary Tree | [go](/Medium/236%20Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree.md) | M |
| 239 | Sliding Window Maximum | [go](/Hard/239%20Sliding%20Window%20Maximum.md) | H |
| 312 | Burst Balloons | [go](/Hard/312%20Burst%20Balloons.md) | H |
| 316 | Remove Duplicate Letters | [go](/Medium/316.%20Remove%20Duplicate%20Letters.md) | M |
| 322 | Coin Change | [go](/Medium/322%20Coin%20Change.md) | M |
| 416 | Partition Equal Subset Sum | [go](/Medium/416%20Partition%20Equal%20Subset%20Sum.md) | M |
| 435 | Non-overlapping Interval | [go](/Medium/435%20Non-overlapping%20Intervals.md) | M |
Expand All @@ -46,8 +47,10 @@
| 875 | Koko Eating Bananas | [go](/Medium/875%20Koko%20Eating%20Bananas.md) | M |
| 881 | Boats to Save People | [go](/Medium/881%20Boats%20to%20Save%20People.md) | M |
| 887 | Super Egg Drop | [go](/Hard/887%20Super%20Egg%20Drop.md) | H |
| 895 | Maximum Frequency Stack | [go](/Hard/895%20Maximum%20Frequency%20Stack.md) | H |
| 912 | Sort an Array | [go](/Medium/912%20Sort%20an%20Array.md) | M |
| 948 | Bag of Tokens | [go](/Medium/948%20Bag%20Of%20Tokens.md) | M |
| 1209 | Remove All Adjacent Duplicates in String II | [go](/Medium/1209%20Remove%20All%20Adjacent%20Duplicates%20in%20String%20II.md) | M |
| 1395 | Count Number of Trams | [go](/Medium/1395%20Count%20Number%20of%20Teams.md) | M |
| 2366 | Mimimum Replacements to Sort the Array | [go](/Hard/2366%20Minimum%20Replacements%20to%20Sort%20the%20Array.md) | H |
| 2444 | Count Subarrays With Fixed Bounds | [go](/Hard/2444%20Count%20Subarrays%20With%20Fixed%20Bounds.md) | H |
Expand Down
Binary file added Week13/1209 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions Week13/1209 Remove All Adjacent Duplicates in String II.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 1209. Remove All Adjacent Duplicates in String II

## Intuition

The problem requires us to remove k adjacent duplicate characters from a string. We can use a stack-based approach where we keep track of both the character and its count. When we encounter k consecutive same characters, we remove them from the stack.

## Approach

1. Create a stack to store pairs of (character, count)
2. Iterate through each character in the string:
- If stack is empty, push the character with count 1
- If current character matches the top of stack:
- Increment the count
- If count reaches k, pop the element from stack
- If current character is different, push it with count 1
3. Finally, reconstruct the string from the stack by repeating each character according to its count

## Complexity

- Time complexity: O(n)
- Space complexity: O(n)

## Keywords

- Stack
- String Manipulation

## Code

```go
func removeDuplicates(s string, k int) string {
type unit struct {
char rune
cnt int
}

st := make([]unit, 0)

for _, char := range s {
if len(st) == 0 {
st = append(st, unit{char: char, cnt: 1})
continue
}
if st[len(st) - 1].char == char {
st[len(st) - 1].cnt += 1
if st[len(st) - 1].cnt == k {
st = st[:len(st) - 1]
}
continue
}
st = append(st, unit{char: char, cnt: 1})
}

ret := ""
for _, u := range st {
for i := 0; i < u.cnt; i += 1 {
ret += string(u.char)
}
}
return ret
}
```
Binary file added Week13/316 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
57 changes: 57 additions & 0 deletions Week13/316. Remove Duplicate Letters.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# 316. Remove Duplicate Letters

## Intuition

The problem requires us to remove duplicate letters from a string while maintaining the lexicographically smallest possible result. We need to ensure that:

1. Each character appears only once in the result
2. The relative order of characters is preserved
3. The result is lexicographically smallest among all possible results

## Approach

1. First, we create a map `lastSeen` to record the last occurrence of each character in the string
2. We use a stack (`st`) to build our result and a set (`seen`) to track characters we've already included
3. For each character in the string:
- If we haven't seen it before, we try to add it to our result
- Before adding, we check if we can remove characters from the stack that are:
- Greater than the current character (to maintain lexicographical order)
- Will appear again later in the string (using lastSeen map)
4. Finally, we convert the stack to a string and return it

## Complexity

- Time complexity: O(n)
- Space complexity: O(n)

## Keywords

- Stack
- Greedy
- String
- Hash Map
- Lexicographical Order

## Code

```go
func removeDuplicateLetters(s string) string {
lastSeen := make(map[rune]int)
for i, c := range s {
lastSeen[c] = i
}

st, seen := make([]rune, 0), make(map[rune]bool)
for i, c := range s {
if !seen[c] {
for len(st) > 0 && c < st[len(st) - 1] && i < lastSeen[st[len(st) - 1]] {
delete(seen, st[len(st) - 1])
st = st[: len(st) - 1]
}
seen[c], st = true, append(st, c)
}
}

return string(st)
}
```
Binary file added Week13/895 AC.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading