Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 23b766d

Browse files
feat: add solutions to lc problem: No.3048 (doocs#2479)
No.3048.Earliest Second to Mark Indices I
1 parent 6465b9b commit 23b766d

File tree

7 files changed

+456
-88
lines changed

7 files changed

+456
-88
lines changed

‎solution/3000-3099/3048.Earliest Second to Mark Indices I/README.md‎

Lines changed: 156 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -82,68 +82,194 @@
8282

8383
## 解法
8484

85-
### 方法一
85+
### 方法一:二分查找
86+
87+
我们注意到,如果我们能够在 $t$ 秒内标记所有下标,那么我们也能在 $t' \geq t$ 秒内标记所有下标。因此,我们可以使用二分查找的方法找到最早的秒数。
88+
89+
我们定义二分查找的左右边界分别为 $l = 1$ 和 $r = m + 1,ドル其中 $m$ 是数组 `changeIndices` 的长度。对于每一个 $t = \frac{l + r}{2},ドル我们检查是否能在 $t$ 秒内标记所有下标。如果能,我们将右边界移动到 $t,ドル否则我们将左边界移动到 $t + 1$。最终,我们判定左边界是否大于 $m,ドル如果是则返回 $-1,ドル否则返回左边界。
90+
91+
题目的关键在于如何判断是否能在 $t$ 秒内标记所有下标。我们可以使用一个数组 $last$ 记录每一个下标最晚需要被标记的时间,用一个变量 $decrement$ 记录当前可以减少的次数,用一个变量 $marked$ 记录已经被标记的下标的数量。
92+
93+
我们遍历数组 `changeIndices` 的前 $t$ 个元素,对于每一个元素 $i,ドル如果 $last[i] = s,ドル那么我们需要检查 $decrement$ 是否大于等于 $nums[i - 1],ドル如果是,我们将 $decrement$ 减去 $nums[i - 1],ドル并且将 $marked$ 加一;否则,我们返回 `False`。如果 $last[i] \neq s,ドル那么我们可以暂时不标记下标,因此将 $decrement$ 加一。最后,我们检查 $marked$ 是否等于 $n,ドル如果是,我们返回 `True`,否则返回 `False`
94+
95+
时间复杂度 $O(m \times \log m),ドル空间复杂度 $O(n)$。其中 $n$ 和 $m$ 分别是数组 `nums``changeIndices` 的长度。
8696

8797
<!-- tabs:start -->
8898

8999
```python
90-
100+
class Solution:
101+
def earliestSecondToMarkIndices(
102+
self, nums: List[int], changeIndices: List[int]
103+
) -> int:
104+
def check(t: int) -> bool:
105+
decrement = 0
106+
marked = 0
107+
last = {i: s for s, i in enumerate(changeIndices[:t])}
108+
for s, i in enumerate(changeIndices[:t]):
109+
if last[i] == s:
110+
if decrement < nums[i - 1]:
111+
return False
112+
decrement -= nums[i - 1]
113+
marked += 1
114+
else:
115+
decrement += 1
116+
return marked == len(nums)
117+
118+
m = len(changeIndices)
119+
l = bisect_left(range(1, m + 2), True, key=check) + 1
120+
return -1 if l > m else l
91121
```
92122

93123
```java
94124
class Solution {
125+
private int[] nums;
126+
private int[] changeIndices;
127+
95128
public int earliestSecondToMarkIndices(int[] nums, int[] changeIndices) {
96-
int l = 0;
97-
int r = changeIndices.length + 1;
129+
this.nums = nums;
130+
this.changeIndices = changeIndices;
131+
int m = changeIndices.length;
132+
int l = 1, r = m + 1;
98133
while (l < r) {
99-
finalint m = (l + r) /2;
100-
if (canMark(nums, changeIndices, m)) {
101-
r = m;
134+
int mid = (l + r) >>1;
135+
if (check(mid)) {
136+
r = mid;
102137
} else {
103-
l = m + 1;
138+
l = mid + 1;
104139
}
105140
}
106-
return l <= changeIndices.length ? l : -1;
141+
return l > m ? -1 : l;
107142
}
108143

109-
private boolean canMark(int[] nums, int[] changeIndices, int second) {
110-
int numMarked = 0;
111-
int decrement = 0;
112-
// indexToLastSecond[i] := the last second to mark the index i
113-
int[] indexToLastSecond = new int[nums.length];
114-
Arrays.fill(indexToLastSecond, -1);
115-
116-
for (int i = 0; i < second; ++i) {
117-
indexToLastSecond[changeIndices[i] - 1] = i;
144+
private boolean check(int t) {
145+
int[] last = new int[nums.length + 1];
146+
for (int s = 0; s < t; ++s) {
147+
last[changeIndices[s]] = s;
118148
}
119-
120-
for (int i = 0; i < second; ++i) {
121-
// Convert to 0-indexed.
122-
final int index = changeIndices[i] - 1;
123-
if (i == indexToLastSecond[index]) {
124-
// Reach the last occurrence of the number.
125-
// So, the current second will be used to mark the index.
126-
if (nums[index] > decrement) {
127-
// The decrement is less than the number to be marked.
149+
int decrement = 0;
150+
int marked = 0;
151+
for (int s = 0; s < t; ++s) {
152+
int i = changeIndices[s];
153+
if (last[i] == s) {
154+
if (decrement < nums[i - 1]) {
128155
return false;
129156
}
130-
decrement -= nums[index];
131-
++numMarked;
157+
decrement -= nums[i -1];
158+
++marked;
132159
} else {
133160
++decrement;
134161
}
135162
}
136-
return numMarked == nums.length;
163+
return marked == nums.length;
137164
}
138165
}
139166
```
140167

141168
```cpp
169+
class Solution {
170+
public:
171+
int earliestSecondToMarkIndices(vector<int>& nums, vector<int>& changeIndices) {
172+
int n = nums.size();
173+
int last[n + 1];
174+
auto check = [&](int t) {
175+
memset(last, 0, sizeof(last));
176+
for (int s = 0; s < t; ++s) {
177+
last[changeIndices[s]] = s;
178+
}
179+
int decrement = 0, marked = 0;
180+
for (int s = 0; s < t; ++s) {
181+
int i = changeIndices[s];
182+
if (last[i] == s) {
183+
if (decrement < nums[i - 1]) {
184+
return false;
185+
}
186+
decrement -= nums[i - 1];
187+
++marked;
188+
} else {
189+
++decrement;
190+
}
191+
}
192+
return marked == n;
193+
};
142194

195+
int m = changeIndices.size();
196+
int l = 1, r = m + 1;
197+
while (l < r) {
198+
int mid = (l + r) >> 1;
199+
if (check(mid)) {
200+
r = mid;
201+
} else {
202+
l = mid + 1;
203+
}
204+
}
205+
return l > m ? -1 : l;
206+
}
207+
};
143208
```
144209

145210
```go
211+
func earliestSecondToMarkIndices(nums []int, changeIndices []int) int {
212+
n, m := len(nums), len(changeIndices)
213+
l := sort.Search(m+1, func(t int) bool {
214+
last := make([]int, n+1)
215+
for s, i := range changeIndices[:t] {
216+
last[i] = s
217+
}
218+
decrement, marked := 0, 0
219+
for s, i := range changeIndices[:t] {
220+
if last[i] == s {
221+
if decrement < nums[i-1] {
222+
return false
223+
}
224+
decrement -= nums[i-1]
225+
marked++
226+
} else {
227+
decrement++
228+
}
229+
}
230+
return marked == n
231+
})
232+
if l > m {
233+
return -1
234+
}
235+
return l
236+
}
237+
```
146238

239+
```ts
240+
function earliestSecondToMarkIndices(nums: number[], changeIndices: number[]): number {
241+
const [n, m] = [nums.length, changeIndices.length];
242+
let [l, r] = [1, m + 1];
243+
const check = (t: number): boolean => {
244+
const last: number[] = Array(n + 1).fill(0);
245+
for (let s = 0; s < t; ++s) {
246+
last[changeIndices[s]] = s;
247+
}
248+
let [decrement, marked] = [0, 0];
249+
for (let s = 0; s < t; ++s) {
250+
const i = changeIndices[s];
251+
if (last[i] === s) {
252+
if (decrement < nums[i - 1]) {
253+
return false;
254+
}
255+
decrement -= nums[i - 1];
256+
++marked;
257+
} else {
258+
++decrement;
259+
}
260+
}
261+
return marked === n;
262+
};
263+
while (l < r) {
264+
const mid = (l + r) >> 1;
265+
if (check(mid)) {
266+
r = mid;
267+
} else {
268+
l = mid + 1;
269+
}
270+
}
271+
return l > m ? -1 : l;
272+
}
147273
```
148274

149275
<!-- tabs:end -->

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /