-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathq3479.py
More file actions
135 lines (108 loc) · 3.73 KB
/
Copy pathq3479.py
File metadata and controls
135 lines (108 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import math
from typing import *
from collections import Counter, deque
"""3479. Fruits Into Baskets III
You are given two arrays of integers, fruits and baskets, each of length n, where fruits[i] represents the quantity of the ith type of fruit, and baskets[j] represents the capacity of the jth basket.
From left to right, place the fruits according to these rules:
Each fruit type must be placed in the leftmost available basket with a capacity greater than or equal to the quantity of that fruit type.
Each basket can hold only one type of fruit.
If a fruit type cannot be placed in any basket, it remains unplaced.
Return the number of fruit types that remain unplaced after all possible allocations are made.
Constraints:
- 1 <= n <= 10^5
- 1 <= fruits[i], baskets[i] <= 10^9
"""
class SegTree:
def __init__(self, arr):
l = len(arr)
self.n = 2 ** math.ceil(math.log2(l))
self.tree = [0] * (self.n * 2)
for i, val in enumerate(arr):
self.update(i + self.n, val)
def update(self, idx, val):
self.tree[idx] = val
while idx > 1:
idx //= 2
self.tree[idx] = max(self.tree[idx * 2], self.tree[idx * 2 + 1])
def query(self, target):
if self.tree[1] < target:
return -1
idx = 1
while idx < self.n:
left, right = idx * 2, idx * 2 + 1
if self.tree[left] >= target:
idx = left
elif self.tree[right] >= target:
idx = right
else:
return idx - self.n
return idx - self.n
class Solution:
# seg tree solution - O(n logn)
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
seg_tree = SegTree(baskets)
ans = 0
for i, n in enumerate(fruits):
idx = seg_tree.query(n)
if idx == -1:
ans += 1
else:
seg_tree.update(idx, -1)
return ans
"""
Someone else's solution I found.
deque approach - O(n^2)
shouldn't pass, but passes
"""
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
ans = 0
dq = deque()
max_b = max(baskets)
for b in baskets:
dq.append(b)
for fruit in fruits:
if fruit > max_b:
ans += 1
continue
buffer = []
found = False
while dq:
basket = dq.popleft()
if basket >= fruit:
found = True
break
else:
buffer.append(basket)
if not found:
ans += 1
while buffer:
dq.appendleft(buffer.pop())
return ans
"""
Cool solution I found:
sqrt decomposition approach - O(n sqrt(n))
"""
def numOfUnplacedFruits(self, fruits: List[int], baskets: List[int]) -> int:
n = len(fruits)
ret = 0
# sqrt decomposition
bucket_sz = int(math.ceil(math.sqrt(n)))
buckets = [[] for _ in range(bucket_sz)]
for i, basket in enumerate(baskets):
bucket_idx = i // bucket_sz
buckets[bucket_idx].append((basket, i))
for bucket in buckets:
bucket.sort()
for cnt in fruits:
for bucket in buckets:
if bucket and bucket[-1][0] >= cnt:
chosen = min((i, basket) for basket, i in bucket if basket >= cnt)
bucket.remove((chosen[1], chosen[0]))
break
else:
ret += 1
return ret
def test_solution():
s = Solution()
if __name__ == "__main__":
test_solution()