Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add solutions to lcp problem: No.19 #1346

Merged
merged 1 commit into from
Jul 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 145 additions & 1 deletion lcp/LCP 19. 秋叶收藏集/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,166 @@

<!-- 这里可写通用的实现逻辑 -->

**方法一:动态规划**

我们定义 $f[i][j]$ 表示对于第 $i$ 片叶子,处于状态 $j$ 时的最小操作次数,其中 $j$ 表示:

- 状态 $0$ 表示第 $i$ 片叶子处于左边的红色部分;
- 状态 $1$ 表示第 $i$ 片叶子处于中间的黄色部分;
- 状态 $2$ 表示第 $i$ 片叶子处于右边的红色部分。

初始时,如果第 $0$ 片叶子为红色,那么 $f[0][0] = 0$,如果第 $0$ 片叶子为黄色,那么 $f[0][0] = 1$。对于其余的状态,我们初始化为 $+\infty$,表示在这种状态下无法完成任务。

考虑 $f[i][j]$,其中 $i \ge 1$:

如果第 $i$ 片叶子为红色,那么 $f[i][0]$ 只能从 $f[i-1][0]$ 转移而来,而 $f[i][1]$ 可以从 $f[i-1][0]$ 和 $f[i-1][1]$ 转移而来,此时需要额外操作一次,而 $f[i][2]$ 可以从 $f[i-1][1]$ 和 $f[i-1][2]$ 转移而来,此时不需要额外操作一次。

如果第 $i$ 片叶子为黄色,那么 $f[i][0]$ 只能从 $f[i-1][0]$ 转移而来,并且需要额外操作一次,而 $f[i][1]$ 可以从 $f[i-1][0]$ 和 $f[i-1][1]$ 转移而来,此时不需要额外操作一次,而 $f[i][2]$ 可以从 $f[i-1][1]$ 和 $f[i-1][2]$ 转移而来,并且需要额外操作一次。

最终的答案即为 $f[n-1][2]$,其中 $n$ 表示红叶和黄叶的总数。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为数组的长度。

<!-- tabs:start -->

### **Python3**

<!-- 这里可写当前语言的特殊实现逻辑 -->

```python

class Solution:
def minimumOperations(self, leaves: str) -> int:
n = len(leaves)
f = [[inf] * 3 for _ in range(n)]
f[0][0] = int(leaves[0] == "y")
for i in range(1, n):
if leaves[i] == "r":
f[i][0] = f[i - 1][0]
f[i][1] = min(f[i - 1][0], f[i - 1][1]) + 1
f[i][2] = min(f[i - 1][2], f[i - 1][1])
else:
f[i][0] = f[i - 1][0] + 1
f[i][1] = min(f[i - 1][0], f[i - 1][1])
f[i][2] = min(f[i - 1][2], f[i - 1][1]) + 1
return f[n - 1][2]
```

### **Java**

<!-- 这里可写当前语言的特殊实现逻辑 -->

```java
class Solution {
public int minimumOperations(String leaves) {
int n = leaves.length();
final int inf = 1 << 30;
var f = new int[n][3];
for (var g : f) {
Arrays.fill(g, inf);
}
f[0][0] = leaves.charAt(0) == 'r' ? 0 : 1;
for (int i = 1; i < n; ++i) {
if (leaves.charAt(i) == 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]);
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}
}
```

### **C++**

```cpp
class Solution {
public:
int minimumOperations(string leaves) {
int n = leaves.size();
int f[n][3];
memset(f, 0x3f, sizeof(f));
f[0][0] = leaves[0] == 'y';
for (int i = 1; i < n; ++i) {
if (leaves[i] == 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = min(f[i - 1][0], f[i - 1][1]);
f[i][2] = min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}
};
```

### **Go**

```go
func minimumOperations(leaves string) int {
n := len(leaves)
f := make([][3]int, n)
inf := 1 << 30
for i := range f {
f[i] = [3]int{inf, inf, inf}
}
if leaves[0] == 'y' {
f[0][0] = 1
} else {
f[0][0] = 0
}
for i := 1; i < n; i++ {
if leaves[i] == 'r' {
f[i][0] = f[i-1][0]
f[i][1] = min(f[i-1][0], f[i-1][1]) + 1
f[i][2] = min(f[i-1][2], f[i-1][1])
} else {
f[i][0] = f[i-1][0] + 1
f[i][1] = min(f[i-1][0], f[i-1][1])
f[i][2] = min(f[i-1][2], f[i-1][1]) + 1
}
}
return f[n-1][2]
}

func min(a, b int) int {
if a < b {
return a
}
return b
}
```

### **TypeScript**

```ts
function minimumOperations(leaves: string): number {
const n = leaves.length;
const inf = 1 << 30;
const f: number[][] = new Array(n)
.fill(0)
.map(() => new Array(3).fill(inf));
f[0][0] = leaves[0] === 'y' ? 1 : 0;
for (let i = 1; i < n; ++i) {
if (leaves[i] === 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]);
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}
```

### **...**
Expand Down
21 changes: 21 additions & 0 deletions lcp/LCP 19. 秋叶收藏集/Solution.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class Solution {
public:
int minimumOperations(string leaves) {
int n = leaves.size();
int f[n][3];
memset(f, 0x3f, sizeof(f));
f[0][0] = leaves[0] == 'y';
for (int i = 1; i < n; ++i) {
if (leaves[i] == 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = min(f[i - 1][0], f[i - 1][1]);
f[i][2] = min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}
};
32 changes: 32 additions & 0 deletions lcp/LCP 19. 秋叶收藏集/Solution.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
func minimumOperations(leaves string) int {
n := len(leaves)
f := make([][3]int, n)
inf := 1 << 30
for i := range f {
f[i] = [3]int{inf, inf, inf}
}
if leaves[0] == 'y' {
f[0][0] = 1
} else {
f[0][0] = 0
}
for i := 1; i < n; i++ {
if leaves[i] == 'r' {
f[i][0] = f[i-1][0]
f[i][1] = min(f[i-1][0], f[i-1][1]) + 1
f[i][2] = min(f[i-1][2], f[i-1][1])
} else {
f[i][0] = f[i-1][0] + 1
f[i][1] = min(f[i-1][0], f[i-1][1])
f[i][2] = min(f[i-1][2], f[i-1][1]) + 1
}
}
return f[n-1][2]
}

func min(a, b int) int {
if a < b {
return a
}
return b
}
23 changes: 23 additions & 0 deletions lcp/LCP 19. 秋叶收藏集/Solution.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
class Solution {
public int minimumOperations(String leaves) {
int n = leaves.length();
final int inf = 1 << 30;
var f = new int[n][3];
for (var g : f) {
Arrays.fill(g, inf);
}
f[0][0] = leaves.charAt(0) == 'r' ? 0 : 1;
for (int i = 1; i < n; ++i) {
if (leaves.charAt(i) == 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]);
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}
}
15 changes: 15 additions & 0 deletions lcp/LCP 19. 秋叶收藏集/Solution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
class Solution:
def minimumOperations(self, leaves: str) -> int:
n = len(leaves)
f = [[inf] * 3 for _ in range(n)]
f[0][0] = int(leaves[0] == "y")
for i in range(1, n):
if leaves[i] == "r":
f[i][0] = f[i - 1][0]
f[i][1] = min(f[i - 1][0], f[i - 1][1]) + 1
f[i][2] = min(f[i - 1][2], f[i - 1][1])
else:
f[i][0] = f[i - 1][0] + 1
f[i][1] = min(f[i - 1][0], f[i - 1][1])
f[i][2] = min(f[i - 1][2], f[i - 1][1]) + 1
return f[n - 1][2]
20 changes: 20 additions & 0 deletions lcp/LCP 19. 秋叶收藏集/Solution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
function minimumOperations(leaves: string): number {
const n = leaves.length;
const inf = 1 << 30;
const f: number[][] = new Array(n)
.fill(0)
.map(() => new Array(3).fill(inf));
f[0][0] = leaves[0] === 'y' ? 1 : 0;
for (let i = 1; i < n; ++i) {
if (leaves[i] === 'r') {
f[i][0] = f[i - 1][0];
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]) + 1;
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]);
} else {
f[i][0] = f[i - 1][0] + 1;
f[i][1] = Math.min(f[i - 1][0], f[i - 1][1]);
f[i][2] = Math.min(f[i - 1][2], f[i - 1][1]) + 1;
}
}
return f[n - 1][2];
}