Skip to content

Commit 62be285

Browse files
committed
feat: 3362
1 parent 0e920e1 commit 62be285

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
# 3362 Zero Array Transformation III
2+
3+
## Intuition
4+
5+
This problem requires us to transform an array to all zeros using a set of queries, where each query [i, j] allows us to decrease all elements from index i to j by 1. The key insight is to use a max heap to track the available ranges and greedily apply them to reduce numbers to zero.
6+
7+
## Approach
8+
9+
1. For each position i, we maintain a list of queries that start at i (start[i])
10+
2. We process the array from left to right:
11+
- For each position i, add all queries starting at i to the max heap
12+
- Calculate how many decrements we need at current position (need)
13+
- Use the available ranges from heap to satisfy the need:
14+
- Remove expired ranges (end < current position)
15+
- Apply ranges greedily, tracking when each range's effect expires
16+
3. If we can't satisfy the need at any position, return -1
17+
4. Return the number of unused queries
18+
19+
## Complexity
20+
21+
- Time complexity: O(N * log Q)
22+
- Space complexity: O(Q)
23+
24+
## Keywords
25+
26+
- Priority Queue (Heap)
27+
- Greedy Algorithm
28+
29+
## Code
30+
31+
```go
32+
type Comparator func(child, parent interface{}) bool
33+
type heap struct {
34+
Storage []interface{}
35+
CmpFunc Comparator
36+
}
37+
38+
func NewHeap(cmpFunc Comparator) *heap {
39+
return &heap {
40+
Storage: append(make([]interface{}, 0), -1),
41+
CmpFunc: cmpFunc,
42+
}
43+
}
44+
45+
func (h *heap) Len() int {
46+
return len(h.Storage) - 1
47+
}
48+
49+
func (h *heap) IsEmpty() bool {
50+
return h.Len() == 0
51+
}
52+
53+
func (h *heap) cmp(child, parent interface{}) bool {
54+
return h.CmpFunc(child, parent)
55+
}
56+
57+
func (h *heap) swap(x, y int) {
58+
h.Storage[x], h.Storage[y] = h.Storage[y], h.Storage[x]
59+
}
60+
61+
func (h *heap) Top() (interface{}, error) {
62+
if h.IsEmpty() {
63+
return nil, errors.New("heap is empty")
64+
}
65+
return h.Storage[1], nil
66+
}
67+
68+
func (h *heap) Push(item interface{}) {
69+
h.Storage = append(h.Storage, item)
70+
now := h.Len()
71+
for now / 2 > 0 && !h.cmp(h.Storage[now], h.Storage[now / 2]) {
72+
h.swap(now, now / 2)
73+
now /= 2
74+
}
75+
}
76+
77+
func (h *heap) Pop() (interface{}, error) {
78+
top, err := h.Top()
79+
if err != nil {
80+
return nil, err
81+
}
82+
last := h.Len()
83+
h.swap(1, last)
84+
h.Storage = h.Storage[: last]
85+
now := 1
86+
for now < last {
87+
left, right := 0, 0
88+
if now * 2 < last && !h.cmp(h.Storage[now * 2], h.Storage[now]) {
89+
left = now * 2
90+
}
91+
if now * 2 + 1 < last && !h.cmp(h.Storage[now * 2 + 1], h.Storage[now]) {
92+
right = now * 2 + 1
93+
}
94+
95+
if left == 0 && right == 0 {
96+
break
97+
} else if left != 0 && right == 0 {
98+
h.swap(now, left)
99+
now = left
100+
} else if left == 0 && right != 0 {
101+
h.swap(now, right)
102+
now = right
103+
} else {
104+
if h.cmp(h.Storage[left], h.Storage[right]) {
105+
h.swap(now, right)
106+
now = right
107+
} else {
108+
h.swap(now, left)
109+
now = left
110+
}
111+
}
112+
}
113+
return top, nil
114+
}
115+
116+
func maxRemoval(nums []int, queries [][]int) int {
117+
cmpFunc := func(child, parent interface{}) bool {
118+
return child.(int) < parent.(int)
119+
}
120+
hp, start, expireAt := NewHeap(cmpFunc), make([][]int, len(nums)), make([]int, len(nums))
121+
for _, q := range queries {
122+
start[q[0]] = append(start[q[0]], q[1])
123+
}
124+
125+
chose, expire := 0, 0
126+
for i, num := range nums {
127+
for _, r := range start[i] {
128+
hp.Push(r)
129+
}
130+
131+
if i > 0 {
132+
expire += expireAt[i - 1]
133+
}
134+
135+
need := num - (chose - expire)
136+
for need > 0 {
137+
for !hp.IsEmpty() {
138+
top, _ := hp.Top()
139+
if top.(int) < i {
140+
hp.Pop()
141+
} else {
142+
break
143+
}
144+
}
145+
if hp.IsEmpty() {
146+
return -1
147+
}
148+
149+
top, _ := hp.Pop()
150+
expireAt[top.(int)] += 1
151+
chose, need = chose + 1, need - 1
152+
}
153+
}
154+
155+
return len(queries) - chose
156+
}
157+
```

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,5 @@
5959
| 2932 | Build A Matrix with Conditions | [go](/Hard/2932%20Build%20A%20Matrix%20With%20Conditions.md) | H |
6060
| 3024 | Type of Triangle | [go](/Easy/3024%20Type%20of%20Triangle.md) | E |
6161
| 3355 | Zero Array Transformation I | [go](/Medium/3355%20Zero%20Array%20Transformation%20I.md) | M |
62+
| 3362 | Zero Array Transformation III | [go](/Medium/3362%20Zero%20Array%20Transformation%20III.md) | M |
6263
| 3727 | Find the Count of Good Integers | [go](/Hard/3727%20Find%20the%20Count%20of%20Good%20Integers.md) | H |

0 commit comments

Comments
 (0)