Skip to content

Commit 238a419

Browse files
authored
feat: add solutions to lc problems: No.2052,2053 (doocs#3367)
* No.2052.Minimum Cost to Separate Sentence Into Rows * No.2053.Kth Distinct String in an Array
1 parent 3e6a439 commit 238a419

File tree

18 files changed

+499
-484
lines changed

18 files changed

+499
-484
lines changed

solution/2000-2099/2052.Minimum Cost to Separate Sentence Into Rows/README.md

+105-73
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,22 @@ tags:
8888

8989
<!-- solution:start -->
9090

91-
### 方法一:记忆化搜索
91+
### 方法一:前缀和 + 记忆化搜索
92+
93+
我们用一个数组 $\textit{nums}$ 记录每个单词的长度,数组的长度记为 $n$。然后我们定义一个长度为 $n + 1$ 的前缀和数组 $\textit{s}$,其中 $\textit{s}[i]$ 表示前 $i$ 个单词的长度之和。
94+
95+
接下来,我们设计一个函数 $\textit{dfs}(i)$,表示从第 $i$ 个单词开始分隔句子的最小成本。那么答案为 $\textit{dfs}(0)$。
96+
97+
函数 $\textit{dfs}(i)$ 的执行过程如下:
98+
99+
- 如果从第 $i$ 个单词开始到最后一个单词的长度之和加上单词之间的空格数小于等于 $k$,那么这些单词可以放在最后一行,成本为 $0$。
100+
- 否则,我们枚举下一个开始分隔的单词的位置 $j$,使得从第 $i$ 个单词到第 $j-1$ 个单词的长度之和加上单词之间的空格数小于等于 $k$。那么 $\textit{dfs}(j)$ 表示从第 $j$ 个单词开始分隔句子的最小成本,而 $(k - m)^2$ 表示将第 $i$ 个单词到第 $j-1$ 个单词放在一行的成本,其中 $m$ 表示从第 $i$ 个单词到第 $j-1$ 个单词的长度之和加上单词之间的空格数。我们枚举所有的 $j$,取最小值即可。
101+
102+
答案即为 $\textit{dfs}(0)$。
103+
104+
为了避免重复计算,我们可以使用记忆化搜索。
105+
106+
时间复杂度 $O(n^2)$,空间复杂度 $O(n)$。其中 $n$ 为单词的个数。
92107

93108
<!-- tabs:start -->
94109

@@ -98,59 +113,56 @@ tags:
98113
class Solution:
99114
def minimumCost(self, sentence: str, k: int) -> int:
100115
@cache
101-
def dfs(i):
102-
if s[-1] - s[i] + n - i - 1 <= k:
116+
def dfs(i: int) -> int:
117+
if s[n] - s[i] + n - i - 1 <= k:
103118
return 0
104-
ans, j = inf, i + 1
105-
while j < n and (t := s[j] - s[i] + j - i - 1) <= k:
106-
ans = min(ans, (k - t) ** 2 + dfs(j))
119+
ans = inf
120+
j = i + 1
121+
while j < n and (m := s[j] - s[i] + j - i - 1) <= k:
122+
ans = min(ans, dfs(j) + (k - m) ** 2)
107123
j += 1
108124
return ans
109125

110-
t = [len(w) for w in sentence.split()]
111-
n = len(t)
112-
s = list(accumulate(t, initial=0))
126+
nums = [len(s) for s in sentence.split()]
127+
n = len(nums)
128+
s = list(accumulate(nums, initial=0))
113129
return dfs(0)
114130
```
115131

116132
#### Java
117133

118134
```java
119135
class Solution {
120-
private static final int INF = Integer.MAX_VALUE;
121-
private int[] memo;
136+
private Integer[] f;
122137
private int[] s;
138+
private int k;
123139
private int n;
124140

125141
public int minimumCost(String sentence, int k) {
142+
this.k = k;
126143
String[] words = sentence.split(" ");
127144
n = words.length;
145+
f = new Integer[n];
128146
s = new int[n + 1];
129147
for (int i = 0; i < n; ++i) {
130148
s[i + 1] = s[i] + words[i].length();
131149
}
132-
memo = new int[n];
133-
Arrays.fill(memo, INF);
134-
return dfs(0, k);
150+
return dfs(0);
135151
}
136152

137-
private int dfs(int i, int k) {
138-
if (memo[i] != INF) {
139-
return memo[i];
140-
}
153+
private int dfs(int i) {
141154
if (s[n] - s[i] + n - i - 1 <= k) {
142-
memo[i] = 0;
143155
return 0;
144156
}
145-
int ans = INF;
146-
for (int j = i + 1; j < n; ++j) {
147-
int t = s[j] - s[i] + j - i - 1;
148-
if (t <= k) {
149-
ans = Math.min(ans, (k - t) * (k - t) + dfs(j, k));
150-
}
157+
if (f[i] != null) {
158+
return f[i];
159+
}
160+
int ans = Integer.MAX_VALUE;
161+
for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) {
162+
int m = s[j] - s[i] + j - i - 1;
163+
ans = Math.min(ans, dfs(j) + (k - m) * (k - m));
151164
}
152-
memo[i] = ans;
153-
return ans;
165+
return f[i] = ans;
154166
}
155167
}
156168
```
@@ -160,34 +172,31 @@ class Solution {
160172
```cpp
161173
class Solution {
162174
public:
163-
const int inf = INT_MAX;
164-
int n;
165-
166175
int minimumCost(string sentence, int k) {
167-
istringstream is(sentence);
168-
vector<string> words;
169-
string word;
170-
while (is >> word) words.push_back(word);
171-
n = words.size();
172-
vector<int> s(n + 1);
173-
for (int i = 0; i < n; ++i) s[i + 1] = s[i] + words[i].size();
174-
vector<int> memo(n, inf);
175-
return dfs(0, k, s, memo);
176-
}
177-
178-
int dfs(int i, int k, vector<int>& s, vector<int>& memo) {
179-
if (memo[i] != inf) return memo[i];
180-
if (s[n] - s[i] + n - i - 1 <= k) {
181-
memo[i] = 0;
182-
return 0;
183-
}
184-
int ans = inf;
185-
for (int j = i + 1; j < n; ++j) {
186-
int t = s[j] - s[i] + j - i - 1;
187-
if (t <= k) ans = min(ans, (k - t) * (k - t) + dfs(j, k, s, memo));
176+
istringstream iss(sentence);
177+
vector<int> s = {0};
178+
string w;
179+
while (iss >> w) {
180+
s.push_back(s.back() + w.size());
188181
}
189-
memo[i] = ans;
190-
return ans;
182+
int n = s.size() - 1;
183+
int f[n];
184+
memset(f, -1, sizeof(f));
185+
auto dfs = [&](auto&& dfs, int i) -> int {
186+
if (s[n] - s[i] + n - i - 1 <= k) {
187+
return 0;
188+
}
189+
if (f[i] != -1) {
190+
return f[i];
191+
}
192+
int ans = INT_MAX;
193+
for (int j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) {
194+
int m = s[j] - s[i] + j - i - 1;
195+
ans = min(ans, dfs(dfs, j) + (k - m) * (k - m));
196+
}
197+
return f[i] = ans;
198+
};
199+
return dfs(dfs, 0);
191200
}
192201
};
193202
```
@@ -196,40 +205,63 @@ public:
196205
197206
```go
198207
func minimumCost(sentence string, k int) int {
199-
words := strings.Split(sentence, " ")
200-
n := len(words)
201-
inf := math.MaxInt32
202-
s := make([]int, n+1)
203-
for i, word := range words {
204-
s[i+1] = s[i] + len(word)
208+
s := []int{0}
209+
for _, w := range strings.Split(sentence, " ") {
210+
s = append(s, s[len(s)-1]+len(w))
205211
}
206-
memo := make([]int, n)
207-
for i := range memo {
208-
memo[i] = inf
212+
n := len(s) - 1
213+
f := make([]int, n)
214+
for i := range f {
215+
f[i] = -1
209216
}
210217
var dfs func(int) int
211218
dfs = func(i int) int {
212-
if memo[i] != inf {
213-
return memo[i]
214-
}
215219
if s[n]-s[i]+n-i-1 <= k {
216-
memo[i] = 0
217220
return 0
218221
}
219-
ans := inf
220-
for j := i + 1; j < n; j++ {
221-
t := s[j] - s[i] + j - i - 1
222-
if t <= k {
223-
ans = min(ans, (k-t)*(k-t)+dfs(j))
224-
}
222+
if f[i] != -1 {
223+
return f[i]
225224
}
226-
memo[i] = ans
225+
ans := math.MaxInt32
226+
for j := i + 1; j < n && s[j]-s[i]+j-i-1 <= k; j++ {
227+
m := s[j] - s[i] + j - i - 1
228+
ans = min(ans, dfs(j)+(k-m)*(k-m))
229+
}
230+
f[i] = ans
227231
return ans
228232
}
229233
return dfs(0)
230234
}
231235
```
232236

237+
#### TypeScript
238+
239+
```ts
240+
function minimumCost(sentence: string, k: number): number {
241+
const s: number[] = [0];
242+
for (const w of sentence.split(' ')) {
243+
s.push(s.at(-1)! + w.length);
244+
}
245+
const n = s.length - 1;
246+
const f: number[] = Array(n).fill(-1);
247+
const dfs = (i: number): number => {
248+
if (s[n] - s[i] + n - i - 1 <= k) {
249+
return 0;
250+
}
251+
if (f[i] !== -1) {
252+
return f[i];
253+
}
254+
let ans = Infinity;
255+
for (let j = i + 1; j < n && s[j] - s[i] + j - i - 1 <= k; ++j) {
256+
const m = s[j] - s[i] + j - i - 1;
257+
ans = Math.min(ans, dfs(j) + (k - m) ** 2);
258+
}
259+
return (f[i] = ans);
260+
};
261+
return dfs(0);
262+
}
263+
```
264+
233265
<!-- tabs:end -->
234266

235267
<!-- solution:end -->

0 commit comments

Comments
 (0)