Skip to content

Commit 96e2310

Browse files
authored
Merge pull request #15 from Alonza0314/2025/05/16
2025/05/16
2 parents e72db2a + 359bf6e commit 96e2310

11 files changed

+399
-0
lines changed
File renamed without changes.

Hard/895 Maximum Frequency Stack.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# 895. Maximum Frequency Stack
2+
3+
## Intuition
4+
5+
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.
6+
7+
## Approach
8+
9+
1. Use a `freqMap` to track the frequency of each element
10+
2. Use a `freqStack` which is a 2D slice where:
11+
- Each inner slice represents elements of the same frequency
12+
- The index of the inner slice represents the frequency level
13+
- Elements in the same inner slice maintain their push order
14+
3. For Push operation:
15+
- If element is new or has frequency -1, add it to frequency level 0
16+
- Otherwise, increment its frequency and add it to the corresponding level
17+
4. For Pop operation:
18+
- Remove the last element from the highest frequency level
19+
- Decrement its frequency in the map
20+
- Remove the frequency level if it becomes empty
21+
22+
## Complexity
23+
24+
- Time complexity: O(1)
25+
- Space complexity: O(n)
26+
27+
## Keywords
28+
29+
- Stack
30+
- Hash Map
31+
32+
## Code
33+
34+
```go
35+
type FreqStack struct {
36+
freqMap map[int]int
37+
freqStack [][]int
38+
}
39+
40+
41+
func Constructor() FreqStack {
42+
f := FreqStack{
43+
freqMap: make(map[int]int),
44+
freqStack: make([][]int, 0),
45+
}
46+
f.freqStack = append(f.freqStack, make([]int, 0))
47+
return f
48+
}
49+
50+
51+
func (f *FreqStack) Push(val int) {
52+
if level, found := f.freqMap[val]; !found || level == -1 {
53+
f.freqStack[0], f.freqMap[val] = append(f.freqStack[0], val), 0
54+
} else {
55+
if len(f.freqStack) - 1 == level {
56+
f.freqStack = append(f.freqStack, make([]int, 0))
57+
}
58+
f.freqStack[level + 1], f.freqMap[val] = append(f.freqStack[level + 1], val), level + 1
59+
}
60+
}
61+
62+
63+
func (f *FreqStack) Pop() int {
64+
tgt := f.freqStack[len(f.freqStack) - 1][len(f.freqStack[len(f.freqStack) - 1]) - 1]
65+
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
66+
if len(f.freqStack[len(f.freqStack) - 1]) == 0 {
67+
f.freqStack = f.freqStack[: len(f.freqStack) - 1]
68+
}
69+
return tgt
70+
}
71+
72+
73+
/**
74+
* Your FreqStack object will be instantiated and called as such:
75+
* obj := Constructor();
76+
* obj.Push(val);
77+
* param_2 := obj.Pop();
78+
*/
79+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# 1209. Remove All Adjacent Duplicates in String II
2+
3+
## Intuition
4+
5+
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.
6+
7+
## Approach
8+
9+
1. Create a stack to store pairs of (character, count)
10+
2. Iterate through each character in the string:
11+
- If stack is empty, push the character with count 1
12+
- If current character matches the top of stack:
13+
- Increment the count
14+
- If count reaches k, pop the element from stack
15+
- If current character is different, push it with count 1
16+
3. Finally, reconstruct the string from the stack by repeating each character according to its count
17+
18+
## Complexity
19+
20+
- Time complexity: O(n)
21+
- Space complexity: O(n)
22+
23+
## Keywords
24+
25+
- Stack
26+
- String Manipulation
27+
28+
## Code
29+
30+
```go
31+
func removeDuplicates(s string, k int) string {
32+
type unit struct {
33+
char rune
34+
cnt int
35+
}
36+
37+
st := make([]unit, 0)
38+
39+
for _, char := range s {
40+
if len(st) == 0 {
41+
st = append(st, unit{char: char, cnt: 1})
42+
continue
43+
}
44+
if st[len(st) - 1].char == char {
45+
st[len(st) - 1].cnt += 1
46+
if st[len(st) - 1].cnt == k {
47+
st = st[:len(st) - 1]
48+
}
49+
continue
50+
}
51+
st = append(st, unit{char: char, cnt: 1})
52+
}
53+
54+
ret := ""
55+
for _, u := range st {
56+
for i := 0; i < u.cnt; i += 1 {
57+
ret += string(u.char)
58+
}
59+
}
60+
return ret
61+
}
62+
```
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# 316. Remove Duplicate Letters
2+
3+
## Intuition
4+
5+
The problem requires us to remove duplicate letters from a string while maintaining the lexicographically smallest possible result. We need to ensure that:
6+
7+
1. Each character appears only once in the result
8+
2. The relative order of characters is preserved
9+
3. The result is lexicographically smallest among all possible results
10+
11+
## Approach
12+
13+
1. First, we create a map `lastSeen` to record the last occurrence of each character in the string
14+
2. We use a stack (`st`) to build our result and a set (`seen`) to track characters we've already included
15+
3. For each character in the string:
16+
- If we haven't seen it before, we try to add it to our result
17+
- Before adding, we check if we can remove characters from the stack that are:
18+
- Greater than the current character (to maintain lexicographical order)
19+
- Will appear again later in the string (using lastSeen map)
20+
4. Finally, we convert the stack to a string and return it
21+
22+
## Complexity
23+
24+
- Time complexity: O(n)
25+
- Space complexity: O(n)
26+
27+
## Keywords
28+
29+
- Stack
30+
- Greedy
31+
- String
32+
- Hash Map
33+
- Lexicographical Order
34+
35+
## Code
36+
37+
```go
38+
func removeDuplicateLetters(s string) string {
39+
lastSeen := make(map[rune]int)
40+
for i, c := range s {
41+
lastSeen[c] = i
42+
}
43+
44+
st, seen := make([]rune, 0), make(map[rune]bool)
45+
for i, c := range s {
46+
if !seen[c] {
47+
for len(st) > 0 && c < st[len(st) - 1] && i < lastSeen[st[len(st) - 1]] {
48+
delete(seen, st[len(st) - 1])
49+
st = st[: len(st) - 1]
50+
}
51+
seen[c], st = true, append(st, c)
52+
}
53+
}
54+
55+
return string(st)
56+
}
57+
```

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
| 236 | Lowest Common Ancestor of a Binary Tree | [go](/Medium/236%20Lowest%20Common%20Ancestor%20of%20a%20Binary%20Tree.md) | M |
3030
| 239 | Sliding Window Maximum | [go](/Hard/239%20Sliding%20Window%20Maximum.md) | H |
3131
| 312 | Burst Balloons | [go](/Hard/312%20Burst%20Balloons.md) | H |
32+
| 316 | Remove Duplicate Letters | [go](/Medium/316.%20Remove%20Duplicate%20Letters.md) | M |
3233
| 322 | Coin Change | [go](/Medium/322%20Coin%20Change.md) | M |
3334
| 416 | Partition Equal Subset Sum | [go](/Medium/416%20Partition%20Equal%20Subset%20Sum.md) | M |
3435
| 435 | Non-overlapping Interval | [go](/Medium/435%20Non-overlapping%20Intervals.md) | M |
@@ -46,8 +47,10 @@
4647
| 875 | Koko Eating Bananas | [go](/Medium/875%20Koko%20Eating%20Bananas.md) | M |
4748
| 881 | Boats to Save People | [go](/Medium/881%20Boats%20to%20Save%20People.md) | M |
4849
| 887 | Super Egg Drop | [go](/Hard/887%20Super%20Egg%20Drop.md) | H |
50+
| 895 | Maximum Frequency Stack | [go](/Hard/895%20Maximum%20Frequency%20Stack.md) | H |
4951
| 912 | Sort an Array | [go](/Medium/912%20Sort%20an%20Array.md) | M |
5052
| 948 | Bag of Tokens | [go](/Medium/948%20Bag%20Of%20Tokens.md) | M |
53+
| 1209 | Remove All Adjacent Duplicates in String II | [go](/Medium/1209%20Remove%20All%20Adjacent%20Duplicates%20in%20String%20II.md) | M |
5154
| 1395 | Count Number of Trams | [go](/Medium/1395%20Count%20Number%20of%20Teams.md) | M |
5255
| 2366 | Mimimum Replacements to Sort the Array | [go](/Hard/2366%20Minimum%20Replacements%20to%20Sort%20the%20Array.md) | H |
5356
| 2444 | Count Subarrays With Fixed Bounds | [go](/Hard/2444%20Count%20Subarrays%20With%20Fixed%20Bounds.md) | H |

Week13/1209 AC.png

113 KB
Loading
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# 1209. Remove All Adjacent Duplicates in String II
2+
3+
## Intuition
4+
5+
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.
6+
7+
## Approach
8+
9+
1. Create a stack to store pairs of (character, count)
10+
2. Iterate through each character in the string:
11+
- If stack is empty, push the character with count 1
12+
- If current character matches the top of stack:
13+
- Increment the count
14+
- If count reaches k, pop the element from stack
15+
- If current character is different, push it with count 1
16+
3. Finally, reconstruct the string from the stack by repeating each character according to its count
17+
18+
## Complexity
19+
20+
- Time complexity: O(n)
21+
- Space complexity: O(n)
22+
23+
## Keywords
24+
25+
- Stack
26+
- String Manipulation
27+
28+
## Code
29+
30+
```go
31+
func removeDuplicates(s string, k int) string {
32+
type unit struct {
33+
char rune
34+
cnt int
35+
}
36+
37+
st := make([]unit, 0)
38+
39+
for _, char := range s {
40+
if len(st) == 0 {
41+
st = append(st, unit{char: char, cnt: 1})
42+
continue
43+
}
44+
if st[len(st) - 1].char == char {
45+
st[len(st) - 1].cnt += 1
46+
if st[len(st) - 1].cnt == k {
47+
st = st[:len(st) - 1]
48+
}
49+
continue
50+
}
51+
st = append(st, unit{char: char, cnt: 1})
52+
}
53+
54+
ret := ""
55+
for _, u := range st {
56+
for i := 0; i < u.cnt; i += 1 {
57+
ret += string(u.char)
58+
}
59+
}
60+
return ret
61+
}
62+
```

Week13/316 AC.png

109 KB
Loading
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# 316. Remove Duplicate Letters
2+
3+
## Intuition
4+
5+
The problem requires us to remove duplicate letters from a string while maintaining the lexicographically smallest possible result. We need to ensure that:
6+
7+
1. Each character appears only once in the result
8+
2. The relative order of characters is preserved
9+
3. The result is lexicographically smallest among all possible results
10+
11+
## Approach
12+
13+
1. First, we create a map `lastSeen` to record the last occurrence of each character in the string
14+
2. We use a stack (`st`) to build our result and a set (`seen`) to track characters we've already included
15+
3. For each character in the string:
16+
- If we haven't seen it before, we try to add it to our result
17+
- Before adding, we check if we can remove characters from the stack that are:
18+
- Greater than the current character (to maintain lexicographical order)
19+
- Will appear again later in the string (using lastSeen map)
20+
4. Finally, we convert the stack to a string and return it
21+
22+
## Complexity
23+
24+
- Time complexity: O(n)
25+
- Space complexity: O(n)
26+
27+
## Keywords
28+
29+
- Stack
30+
- Greedy
31+
- String
32+
- Hash Map
33+
- Lexicographical Order
34+
35+
## Code
36+
37+
```go
38+
func removeDuplicateLetters(s string) string {
39+
lastSeen := make(map[rune]int)
40+
for i, c := range s {
41+
lastSeen[c] = i
42+
}
43+
44+
st, seen := make([]rune, 0), make(map[rune]bool)
45+
for i, c := range s {
46+
if !seen[c] {
47+
for len(st) > 0 && c < st[len(st) - 1] && i < lastSeen[st[len(st) - 1]] {
48+
delete(seen, st[len(st) - 1])
49+
st = st[: len(st) - 1]
50+
}
51+
seen[c], st = true, append(st, c)
52+
}
53+
}
54+
55+
return string(st)
56+
}
57+
```

Week13/895 AC.png

120 KB
Loading

0 commit comments

Comments
 (0)