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 ad0ff4f

Browse files
feat: add solutions to lc problem: No.1745 (#4109)
No.1745.Palindrome Partitioning IV
1 parent 0a017c9 commit ad0ff4f

File tree

7 files changed

+156
-61
lines changed

7 files changed

+156
-61
lines changed

‎solution/1700-1799/1745.Palindrome Partitioning IV/README.md‎

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,26 @@ tags:
5656

5757
<!-- solution:start -->
5858

59-
### 方法一:预处理 + 枚举
59+
### 方法一:动态规划
6060

61-
预处理出字符串 `s` 的所有子串是否为回文串,然后枚举 `s` 的所有分割点,判断是否满足条件
61+
我们定义 $f[i][j]$ 表示字符串 $s$ 的第 $i$ 个字符到第 $j$ 个字符是否为回文串,初始时 $f[i][j] = \textit{true}$
6262

63-
时间复杂度 $O(n^2),ドル空间复杂度 $O(n^2)$。其中 $n$ 为字符串 `s` 的长度。
63+
然后我们可以通过以下的状态转移方程来计算 $f[i][j]$:
64+
65+
$$
66+
f[i][j] = \begin{cases}
67+
\textit{true}, & \text{if } s[i] = s[j] \text{ and } (i + 1 = j \text{ or } f[i + 1][j - 1]) \\
68+
\textit{false}, & \text{otherwise}
69+
\end{cases}
70+
$$
71+
72+
由于 $f[i][j]$ 依赖于 $f[i + 1][j - 1],ドル因此,我们需要从大到小的顺序枚举 $i,ドル从小到大的顺序枚举 $j,ドル这样才能保证当计算 $f[i][j]$ 时 $f[i + 1][j - 1]$ 已经被计算过。
73+
74+
接下来,我们枚举第一个子串的右端点 $i,ドル第二个子串的右端点 $j,ドル那么第三个子串的左端点可以枚举的范围为 $[j + 1, n - 1],ドル其中 $n$ 是字符串 $s$ 的长度。如果第一个子串 $s[0..i]$、第二个子串 $s[i+1..j]$ 和第三个子串 $s[j+1..n-1]$ 都是回文串,那么我们就找到了一种可行的分割方案,返回 $\textit{true}$。
75+
76+
枚举完所有的分割方案后,如果没有找到符合要求的分割方案,那么返回 $\textit{false}$。
77+
78+
时间复杂度 $O(n^2),ドル空间复杂度 $O(n^2)$。其中 $n$ 是字符串 $s$ 的长度。
6479

6580
<!-- tabs:start -->
6681

@@ -70,13 +85,13 @@ tags:
7085
class Solution:
7186
def checkPartitioning(self, s: str) -> bool:
7287
n = len(s)
73-
g = [[True] * n for _ in range(n)]
88+
f = [[True] * n for _ in range(n)]
7489
for i in range(n - 1, -1, -1):
7590
for j in range(i + 1, n):
76-
g[i][j] = s[i] == s[j] and (i + 1 == j or g[i + 1][j - 1])
91+
f[i][j] = s[i] == s[j] and (i + 1 == j or f[i + 1][j - 1])
7792
for i in range(n - 2):
7893
for j in range(i + 1, n - 1):
79-
if g[0][i] and g[i + 1][j] and g[j + 1][-1]:
94+
if f[0][i] and f[i + 1][j] and f[j + 1][-1]:
8095
return True
8196
return False
8297
```
@@ -87,18 +102,18 @@ class Solution:
87102
class Solution {
88103
public boolean checkPartitioning(String s) {
89104
int n = s.length();
90-
boolean[][] g = new boolean[n][n];
91-
for (var e : g) {
92-
Arrays.fill(e, true);
105+
boolean[][] f = new boolean[n][n];
106+
for (var g : f) {
107+
Arrays.fill(g, true);
93108
}
94109
for (int i = n - 1; i >= 0; --i) {
95110
for (int j = i + 1; j < n; ++j) {
96-
g[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || g[i + 1][j - 1]);
111+
f[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || f[i + 1][j - 1]);
97112
}
98113
}
99114
for (int i = 0; i < n - 2; ++i) {
100115
for (int j = i + 1; j < n - 1; ++j) {
101-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
116+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
102117
return true;
103118
}
104119
}
@@ -115,15 +130,15 @@ class Solution {
115130
public:
116131
bool checkPartitioning(string s) {
117132
int n = s.size();
118-
vector<vector<bool>> g(n, vector<bool>(n, true));
133+
vector<vector<bool>> f(n, vector<bool>(n, true));
119134
for (int i = n - 1; i >= 0; --i) {
120135
for (int j = i + 1; j < n; ++j) {
121-
g[i][j] = s[i] == s[j] && (i + 1 == j || g[i + 1][j - 1]);
136+
f[i][j] = s[i] == s[j] && (i + 1 == j || f[i + 1][j - 1]);
122137
}
123138
}
124139
for (int i = 0; i < n - 2; ++i) {
125140
for (int j = i + 1; j < n - 1; ++j) {
126-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
141+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
127142
return true;
128143
}
129144
}
@@ -138,21 +153,21 @@ public:
138153
```go
139154
func checkPartitioning(s string) bool {
140155
n := len(s)
141-
g := make([][]bool, n)
142-
for i := range g {
143-
g[i] = make([]bool, n)
144-
for j := range g[i] {
145-
g[i][j] = true
156+
f := make([][]bool, n)
157+
for i := range f {
158+
f[i] = make([]bool, n)
159+
for j := range f[i] {
160+
f[i][j] = true
146161
}
147162
}
148163
for i := n - 1; i >= 0; i-- {
149164
for j := i + 1; j < n; j++ {
150-
g[i][j] = s[i] == s[j] && (i+1 == j || g[i+1][j-1])
165+
f[i][j] = s[i] == s[j] && (i+1 == j || f[i+1][j-1])
151166
}
152167
}
153168
for i := 0; i < n-2; i++ {
154169
for j := i + 1; j < n-1; j++ {
155-
if g[0][i] && g[i+1][j] && g[j+1][n-1] {
170+
if f[0][i] && f[i+1][j] && f[j+1][n-1] {
156171
return true
157172
}
158173
}
@@ -161,6 +176,28 @@ func checkPartitioning(s string) bool {
161176
}
162177
```
163178

179+
#### TypeScript
180+
181+
```ts
182+
function checkPartitioning(s: string): boolean {
183+
const n = s.length;
184+
const f: boolean[][] = Array.from({ length: n }, () => Array(n).fill(true));
185+
for (let i = n - 1; i >= 0; --i) {
186+
for (let j = i + 1; j < n; ++j) {
187+
f[i][j] = s[i] === s[j] && f[i + 1][j - 1];
188+
}
189+
}
190+
for (let i = 0; i < n - 2; ++i) {
191+
for (let j = i + 1; j < n - 1; ++j) {
192+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
193+
return true;
194+
}
195+
}
196+
}
197+
return false;
198+
}
199+
```
200+
164201
<!-- tabs:end -->
165202

166203
<!-- solution:end -->

‎solution/1700-1799/1745.Palindrome Partitioning IV/README_EN.md‎

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,26 @@ tags:
5454

5555
<!-- solution:start -->
5656

57-
### Solution 1
57+
### Solution 1: Dynamic Programming
58+
59+
We define $f[i][j]$ to indicate whether the substring of $s$ from the $i$-th character to the $j$-th character is a palindrome, initially $f[i][j] = \textit{true}$.
60+
61+
Then we can calculate $f[i][j]$ using the following state transition equation:
62+
63+
$$
64+
f[i][j] = \begin{cases}
65+
\textit{true}, & \text{if } s[i] = s[j] \text{ and } (i + 1 = j \text{ or } f[i + 1][j - 1]) \\
66+
\textit{false}, & \text{otherwise}
67+
\end{cases}
68+
$$
69+
70+
Since $f[i][j]$ depends on $f[i + 1][j - 1],ドル we need to enumerate $i$ from large to small and $j$ from small to large, so that when calculating $f[i][j],ドル $f[i + 1][j - 1]$ has already been calculated.
71+
72+
Next, we enumerate the right endpoint $i$ of the first substring and the right endpoint $j$ of the second substring. The left endpoint of the third substring can be enumerated in the range $[j + 1, n - 1],ドル where $n$ is the length of the string $s$. If the first substring $s[0..i],ドル the second substring $s[i+1..j],ドル and the third substring $s[j+1..n-1]$ are all palindromes, then we have found a feasible partitioning scheme and return $\textit{true}$.
73+
74+
After enumerating all partitioning schemes, if no valid partitioning scheme is found, return $\textit{false}$.
75+
76+
Time complexity is $O(n^2),ドル and space complexity is $O(n^2)$. Where $n$ is the length of the string $s$.
5877

5978
<!-- tabs:start -->
6079

@@ -64,13 +83,13 @@ tags:
6483
class Solution:
6584
def checkPartitioning(self, s: str) -> bool:
6685
n = len(s)
67-
g = [[True] * n for _ in range(n)]
86+
f = [[True] * n for _ in range(n)]
6887
for i in range(n - 1, -1, -1):
6988
for j in range(i + 1, n):
70-
g[i][j] = s[i] == s[j] and (i + 1 == j or g[i + 1][j - 1])
89+
f[i][j] = s[i] == s[j] and (i + 1 == j or f[i + 1][j - 1])
7190
for i in range(n - 2):
7291
for j in range(i + 1, n - 1):
73-
if g[0][i] and g[i + 1][j] and g[j + 1][-1]:
92+
if f[0][i] and f[i + 1][j] and f[j + 1][-1]:
7493
return True
7594
return False
7695
```
@@ -81,18 +100,18 @@ class Solution:
81100
class Solution {
82101
public boolean checkPartitioning(String s) {
83102
int n = s.length();
84-
boolean[][] g = new boolean[n][n];
85-
for (var e : g) {
86-
Arrays.fill(e, true);
103+
boolean[][] f = new boolean[n][n];
104+
for (var g : f) {
105+
Arrays.fill(g, true);
87106
}
88107
for (int i = n - 1; i >= 0; --i) {
89108
for (int j = i + 1; j < n; ++j) {
90-
g[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || g[i + 1][j - 1]);
109+
f[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || f[i + 1][j - 1]);
91110
}
92111
}
93112
for (int i = 0; i < n - 2; ++i) {
94113
for (int j = i + 1; j < n - 1; ++j) {
95-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
114+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
96115
return true;
97116
}
98117
}
@@ -109,15 +128,15 @@ class Solution {
109128
public:
110129
bool checkPartitioning(string s) {
111130
int n = s.size();
112-
vector<vector<bool>> g(n, vector<bool>(n, true));
131+
vector<vector<bool>> f(n, vector<bool>(n, true));
113132
for (int i = n - 1; i >= 0; --i) {
114133
for (int j = i + 1; j < n; ++j) {
115-
g[i][j] = s[i] == s[j] && (i + 1 == j || g[i + 1][j - 1]);
134+
f[i][j] = s[i] == s[j] && (i + 1 == j || f[i + 1][j - 1]);
116135
}
117136
}
118137
for (int i = 0; i < n - 2; ++i) {
119138
for (int j = i + 1; j < n - 1; ++j) {
120-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
139+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
121140
return true;
122141
}
123142
}
@@ -132,21 +151,21 @@ public:
132151
```go
133152
func checkPartitioning(s string) bool {
134153
n := len(s)
135-
g := make([][]bool, n)
136-
for i := range g {
137-
g[i] = make([]bool, n)
138-
for j := range g[i] {
139-
g[i][j] = true
154+
f := make([][]bool, n)
155+
for i := range f {
156+
f[i] = make([]bool, n)
157+
for j := range f[i] {
158+
f[i][j] = true
140159
}
141160
}
142161
for i := n - 1; i >= 0; i-- {
143162
for j := i + 1; j < n; j++ {
144-
g[i][j] = s[i] == s[j] && (i+1 == j || g[i+1][j-1])
163+
f[i][j] = s[i] == s[j] && (i+1 == j || f[i+1][j-1])
145164
}
146165
}
147166
for i := 0; i < n-2; i++ {
148167
for j := i + 1; j < n-1; j++ {
149-
if g[0][i] && g[i+1][j] && g[j+1][n-1] {
168+
if f[0][i] && f[i+1][j] && f[j+1][n-1] {
150169
return true
151170
}
152171
}
@@ -155,6 +174,28 @@ func checkPartitioning(s string) bool {
155174
}
156175
```
157176

177+
#### TypeScript
178+
179+
```ts
180+
function checkPartitioning(s: string): boolean {
181+
const n = s.length;
182+
const f: boolean[][] = Array.from({ length: n }, () => Array(n).fill(true));
183+
for (let i = n - 1; i >= 0; --i) {
184+
for (let j = i + 1; j < n; ++j) {
185+
f[i][j] = s[i] === s[j] && f[i + 1][j - 1];
186+
}
187+
}
188+
for (let i = 0; i < n - 2; ++i) {
189+
for (let j = i + 1; j < n - 1; ++j) {
190+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
191+
return true;
192+
}
193+
}
194+
}
195+
return false;
196+
}
197+
```
198+
158199
<!-- tabs:end -->
159200

160201
<!-- solution:end -->

‎solution/1700-1799/1745.Palindrome Partitioning IV/Solution.cpp‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ class Solution {
22
public:
33
bool checkPartitioning(string s) {
44
int n = s.size();
5-
vector<vector<bool>> g(n, vector<bool>(n, true));
5+
vector<vector<bool>> f(n, vector<bool>(n, true));
66
for (int i = n - 1; i >= 0; --i) {
77
for (int j = i + 1; j < n; ++j) {
8-
g[i][j] = s[i] == s[j] && (i + 1 == j || g[i + 1][j - 1]);
8+
f[i][j] = s[i] == s[j] && (i + 1 == j || f[i + 1][j - 1]);
99
}
1010
}
1111
for (int i = 0; i < n - 2; ++i) {
1212
for (int j = i + 1; j < n - 1; ++j) {
13-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
13+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
1414
return true;
1515
}
1616
}
1717
}
1818
return false;
1919
}
20-
};
20+
};
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
11
func checkPartitioning(s string) bool {
22
n := len(s)
3-
g := make([][]bool, n)
4-
for i := range g {
5-
g[i] = make([]bool, n)
6-
for j := range g[i] {
7-
g[i][j] = true
3+
f := make([][]bool, n)
4+
for i := range f {
5+
f[i] = make([]bool, n)
6+
for j := range f[i] {
7+
f[i][j] = true
88
}
99
}
1010
for i := n - 1; i >= 0; i-- {
1111
for j := i + 1; j < n; j++ {
12-
g[i][j] = s[i] == s[j] && (i+1 == j || g[i+1][j-1])
12+
f[i][j] = s[i] == s[j] && (i+1 == j || f[i+1][j-1])
1313
}
1414
}
1515
for i := 0; i < n-2; i++ {
1616
for j := i + 1; j < n-1; j++ {
17-
if g[0][i] && g[i+1][j] && g[j+1][n-1] {
17+
if f[0][i] && f[i+1][j] && f[j+1][n-1] {
1818
return true
1919
}
2020
}
2121
}
2222
return false
23-
}
23+
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
class Solution {
22
public boolean checkPartitioning(String s) {
33
int n = s.length();
4-
boolean[][] g = new boolean[n][n];
5-
for (var e : g) {
6-
Arrays.fill(e, true);
4+
boolean[][] f = new boolean[n][n];
5+
for (var g : f) {
6+
Arrays.fill(g, true);
77
}
88
for (int i = n - 1; i >= 0; --i) {
99
for (int j = i + 1; j < n; ++j) {
10-
g[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || g[i + 1][j - 1]);
10+
f[i][j] = s.charAt(i) == s.charAt(j) && (i + 1 == j || f[i + 1][j - 1]);
1111
}
1212
}
1313
for (int i = 0; i < n - 2; ++i) {
1414
for (int j = i + 1; j < n - 1; ++j) {
15-
if (g[0][i] && g[i + 1][j] && g[j + 1][n - 1]) {
15+
if (f[0][i] && f[i + 1][j] && f[j + 1][n - 1]) {
1616
return true;
1717
}
1818
}
1919
}
2020
return false;
2121
}
22-
}
22+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
class Solution:
22
def checkPartitioning(self, s: str) -> bool:
33
n = len(s)
4-
g = [[True] * n for _ in range(n)]
4+
f = [[True] * n for _ in range(n)]
55
for i in range(n - 1, -1, -1):
66
for j in range(i + 1, n):
7-
g[i][j] = s[i] == s[j] and (i + 1 == j or g[i + 1][j - 1])
7+
f[i][j] = s[i] == s[j] and (i + 1 == j or f[i + 1][j - 1])
88
for i in range(n - 2):
99
for j in range(i + 1, n - 1):
10-
if g[0][i] and g[i + 1][j] and g[j + 1][-1]:
10+
if f[0][i] and f[i + 1][j] and f[j + 1][-1]:
1111
return True
1212
return False

0 commit comments

Comments
(0)

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