Skip to content

Commit 3084bbc

Browse files
committed
feat: add solutions to lc problem: No.3777
1 parent 299056a commit 3084bbc

File tree

7 files changed

+934
-8
lines changed

7 files changed

+934
-8
lines changed

solution/3700-3799/3777.Minimum Deletions to Make Alternating Substring/README.md

Lines changed: 315 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,32 +244,343 @@ edit_url: https://github.com/doocs/leetcode/edit/main/solution/3700-3799/3777.Mi
244244

245245
<!-- solution:start -->
246246

247-
### 方法一
247+
### 方法一:树状数组
248+
249+
我们可以将字符串 $s$ 转换为一个长度为 $n$ 的数组 $\textit{nums}$,其中 $\textit{nums}[0] = 0$,对于 $1 \leq i < n$,如果 $s[i] = s[i-1]$,则 $\textit{nums}[i] = 1$,否则 $\textit{nums}[i] = 0$。这样 $\textit{nums}[i]$ 表示在索引 $i$ 处是否存在相邻且相等的字符。那么我们计算区间 $[l, r]$ 内使子字符串 $s[l..r]$ 变成交替字符串所需的最小字符删除数就等价于计算 $\textit{nums}$ 数组在区间 $[l+1, r]$ 上的元素和。
250+
251+
为了高效地处理查询,我们可以使用树状数组来维护 $\textit{nums}$ 数组的前缀和。对于类型为 $[1, j]$ 的查询,我们需要将 $\textit{nums}[j]$ 和 $\textit{nums}[j+1]$(如果 $j+1 < n$)进行翻转,并更新树状数组。对于类型为 $[2, l, r]$ 的查询,我们可以通过树状数组快速计算区间 $[l+1, r]$ 上的元素和。
252+
253+
时间复杂度 $O((n + q) \log n)$,空间复杂度 $O(n)$。其中 $n$ 是字符串 $s$ 的长度,而 $q$ 是查询的数量。
248254

249255
<!-- tabs:start -->
250256

251257
#### Python3
252258

253259
```python
254-
260+
class BinaryIndexedTree:
261+
__slots__ = "n", "c"
262+
263+
def __init__(self, n: int):
264+
self.n = n
265+
self.c = [0] * (n + 1)
266+
267+
def update(self, x: int, delta: int) -> None:
268+
while x <= self.n:
269+
self.c[x] += delta
270+
x += x & -x
271+
272+
def query(self, x: int) -> int:
273+
s = 0
274+
while x:
275+
s += self.c[x]
276+
x -= x & -x
277+
return s
278+
279+
280+
class Solution:
281+
def minDeletions(self, s: str, queries: List[List[int]]) -> List[int]:
282+
n = len(s)
283+
nums = [0] * n
284+
bit = BinaryIndexedTree(n)
285+
for i in range(1, n):
286+
nums[i] = int(s[i] == s[i - 1])
287+
if nums[i]:
288+
bit.update(i + 1, 1)
289+
ans = []
290+
for q in queries:
291+
if q[0] == 1:
292+
j = q[1]
293+
delta = (nums[j] ^ 1) - nums[j]
294+
nums[j] ^= 1
295+
bit.update(j + 1, delta)
296+
if j + 1 < n:
297+
delta = (nums[j + 1] ^ 1) - nums[j + 1]
298+
nums[j + 1] ^= 1
299+
bit.update(j + 2, delta)
300+
else:
301+
_, l, r = q
302+
ans.append(bit.query(r + 1) - bit.query(l + 1))
303+
return ans
255304
```
256305

257306
#### Java
258307

259308
```java
260-
309+
class BinaryIndexedTree {
310+
int n;
311+
int[] c;
312+
313+
BinaryIndexedTree(int n) {
314+
this.n = n;
315+
this.c = new int[n + 1];
316+
}
317+
318+
void update(int x, int delta) {
319+
while (x <= n) {
320+
c[x] += delta;
321+
x += x & -x;
322+
}
323+
}
324+
325+
int query(int x) {
326+
int s = 0;
327+
while (x > 0) {
328+
s += c[x];
329+
x -= x & -x;
330+
}
331+
return s;
332+
}
333+
}
334+
335+
class Solution {
336+
public int[] minDeletions(String s, int[][] queries) {
337+
int n = s.length();
338+
int[] nums = new int[n];
339+
BinaryIndexedTree bit = new BinaryIndexedTree(n);
340+
341+
for (int i = 1; i < n; i++) {
342+
nums[i] = (s.charAt(i) == s.charAt(i - 1)) ? 1 : 0;
343+
if (nums[i] == 1) {
344+
bit.update(i + 1, 1);
345+
}
346+
}
347+
348+
int cnt = 0;
349+
for (int[] q : queries) {
350+
if (q[0] == 2) {
351+
cnt++;
352+
}
353+
}
354+
355+
int[] ans = new int[cnt];
356+
int idx = 0;
357+
358+
for (int[] q : queries) {
359+
if (q[0] == 1) {
360+
int j = q[1];
361+
362+
int delta = (nums[j] ^ 1) - nums[j];
363+
nums[j] ^= 1;
364+
bit.update(j + 1, delta);
365+
366+
if (j + 1 < n) {
367+
delta = (nums[j + 1] ^ 1) - nums[j + 1];
368+
nums[j + 1] ^= 1;
369+
bit.update(j + 2, delta);
370+
}
371+
} else {
372+
int l = q[1];
373+
int r = q[2];
374+
ans[idx++] = bit.query(r + 1) - bit.query(l + 1);
375+
}
376+
}
377+
return ans;
378+
}
379+
}
261380
```
262381

263382
#### C++
264383

265384
```cpp
266-
385+
class BinaryIndexedTree {
386+
public:
387+
int n;
388+
vector<int> c;
389+
390+
BinaryIndexedTree(int n)
391+
: n(n)
392+
, c(n + 1, 0) {}
393+
394+
void update(int x, int delta) {
395+
while (x <= n) {
396+
c[x] += delta;
397+
x += x & -x;
398+
}
399+
}
400+
401+
int query(int x) {
402+
int s = 0;
403+
while (x > 0) {
404+
s += c[x];
405+
x -= x & -x;
406+
}
407+
return s;
408+
}
409+
};
410+
411+
class Solution {
412+
public:
413+
vector<int> minDeletions(string s, vector<vector<int>>& queries) {
414+
int n = s.size();
415+
vector<int> nums(n, 0);
416+
BinaryIndexedTree bit(n);
417+
418+
for (int i = 1; i < n; i++) {
419+
nums[i] = (s[i] == s[i - 1]);
420+
if (nums[i]) {
421+
bit.update(i + 1, 1);
422+
}
423+
}
424+
425+
vector<int> ans;
426+
427+
for (auto& q : queries) {
428+
if (q[0] == 1) {
429+
int j = q[1];
430+
431+
int delta = (nums[j] ^ 1) - nums[j];
432+
nums[j] ^= 1;
433+
bit.update(j + 1, delta);
434+
435+
if (j + 1 < n) {
436+
delta = (nums[j + 1] ^ 1) - nums[j + 1];
437+
nums[j + 1] ^= 1;
438+
bit.update(j + 2, delta);
439+
}
440+
} else {
441+
int l = q[1];
442+
int r = q[2];
443+
ans.push_back(bit.query(r + 1) - bit.query(l + 1));
444+
}
445+
}
446+
return ans;
447+
}
448+
};
267449
```
268450
269451
#### Go
270452
271453
```go
454+
type binaryIndexedTree struct {
455+
n int
456+
c []int
457+
}
458+
459+
func newBinaryIndexedTree(n int) *binaryIndexedTree {
460+
return &binaryIndexedTree{
461+
n: n,
462+
c: make([]int, n+1),
463+
}
464+
}
465+
466+
func (bit *binaryIndexedTree) update(x, delta int) {
467+
for x <= bit.n {
468+
bit.c[x] += delta
469+
x += x & -x
470+
}
471+
}
472+
473+
func (bit *binaryIndexedTree) query(x int) int {
474+
s := 0
475+
for x > 0 {
476+
s += bit.c[x]
477+
x -= x & -x
478+
}
479+
return s
480+
}
481+
482+
func minDeletions(s string, queries [][]int) []int {
483+
n := len(s)
484+
nums := make([]int, n)
485+
bit := newBinaryIndexedTree(n)
486+
487+
for i := 1; i < n; i++ {
488+
if s[i] == s[i-1] {
489+
nums[i] = 1
490+
bit.update(i+1, 1)
491+
}
492+
}
493+
494+
ans := make([]int, 0)
495+
496+
for _, q := range queries {
497+
if q[0] == 1 {
498+
j := q[1]
499+
500+
delta := (nums[j] ^ 1 - nums[j])
501+
nums[j] ^= 1
502+
bit.update(j+1, delta)
503+
504+
if j+1 < n {
505+
delta = (nums[j+1] ^ 1 - nums[j+1])
506+
nums[j+1] ^= 1
507+
bit.update(j+2, delta)
508+
}
509+
} else {
510+
l, r := q[1], q[2]
511+
ans = append(ans, bit.query(r+1)-bit.query(l+1))
512+
}
513+
}
514+
515+
return ans
516+
}
517+
```
272518

519+
#### TypeScript
520+
521+
```ts
522+
class BinaryIndexedTree {
523+
n: number;
524+
c: number[];
525+
526+
constructor(n: number) {
527+
this.n = n;
528+
this.c = Array(n + 1).fill(0);
529+
}
530+
531+
update(x: number, delta: number): void {
532+
while (x <= this.n) {
533+
this.c[x] += delta;
534+
x += x & -x;
535+
}
536+
}
537+
538+
query(x: number): number {
539+
let s = 0;
540+
while (x > 0) {
541+
s += this.c[x];
542+
x -= x & -x;
543+
}
544+
return s;
545+
}
546+
}
547+
548+
function minDeletions(s: string, queries: number[][]): number[] {
549+
const n = s.length;
550+
const nums: number[] = Array(n).fill(0);
551+
const bit = new BinaryIndexedTree(n);
552+
553+
for (let i = 1; i < n; i++) {
554+
if (s[i] === s[i - 1]) {
555+
nums[i] = 1;
556+
bit.update(i + 1, 1);
557+
}
558+
}
559+
560+
const ans: number[] = [];
561+
562+
for (const q of queries) {
563+
if (q[0] === 1) {
564+
const j = q[1];
565+
566+
let delta = (nums[j] ^ 1) - nums[j];
567+
nums[j] ^= 1;
568+
bit.update(j + 1, delta);
569+
570+
if (j + 1 < n) {
571+
delta = (nums[j + 1] ^ 1) - nums[j + 1];
572+
nums[j + 1] ^= 1;
573+
bit.update(j + 2, delta);
574+
}
575+
} else {
576+
const l = q[1],
577+
r = q[2];
578+
ans.push(bit.query(r + 1) - bit.query(l + 1));
579+
}
580+
}
581+
582+
return ans;
583+
}
273584
```
274585

275586
<!-- tabs:end -->

0 commit comments

Comments
 (0)