将句子分隔成行的最低成本
难度:
标签:
题目描述
代码结果
运行时间: 36 ms, 内存: 16.2 MB
/*
* 题目思路:
* 给定一个句子和一个最大行宽度,将句子分隔成多行,要求每行的宽度尽可能均匀,最小化宽度与平均宽度的偏差。
* 使用Java Stream方法,首先计算每个单词在不同位置分割的最小成本。
* 然后使用Stream方法进行处理和计算。
*/
import java.util.*;
import java.util.stream.*;
public class SentenceSplitterStream {
public int minCostToSplit(String sentence, int maxWidth) {
String[] words = sentence.split(" ");
int n = words.length;
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE);
dp[n] = 0;
IntStream.range(0, n).boxed().sorted(Comparator.reverseOrder()).forEach(i -> {
int lineLength = 0;
for (int j = i; j < n; j++) {
lineLength += words[j].length();
if (j > i) lineLength++; // 加上空格
if (lineLength > maxWidth) break;
int cost = (maxWidth - lineLength) * (maxWidth - lineLength);
if (j == n - 1) cost = 0;
dp[i] = Math.min(dp[i], cost + dp[j + 1]);
}
});
return dp[0];
}
public static void main(String[] args) {
SentenceSplitterStream splitter = new SentenceSplitterStream();
String sentence = "This is a sample sentence for splitting";
int maxWidth = 10;
System.out.println(splitter.minCostToSplit(sentence, maxWidth));
}
}
解释
方法:
该题解采用动态规划方法来解决问题。首先,通过`endings`数组计算每个词到句首的累积长度,包括空格。`dp[i]`表示从单词i开始到句子末尾的最小成本。从句子的末尾开始计算dp值,逐步向前推进。如果从当前单词i到句尾的所有单词长度和小于等于k,则dp[i]为0(因为所有单词都可以放在一行)。否则,需要计算将单词分成多行时的最小成本,即考虑每一个可能的断点j,计算从i到j的单词放在一行时的剩余空间的平方(作为成本),加上从j+1开始的最小成本。最终,dp[0]将给出整个句子的最低分隔成本。
时间复杂度:
O(N^2)
空间复杂度:
O(N)
代码细节讲解
🦆
在动态规划中,`dp[i]`数组是如何初始化的,为什么初始值设置为无穷大?
▷🦆
如何确保`endings`数组正确计算了每个词到句首的累积长度,包括空格?
▷🦆
循环中使用的`takewhile`函数是如何工作的,它在这里起到了什么作用?
▷🦆
算法在处理边界情况,如单个单词长度超过k,或所有单词长度和刚好等于k时的表现如何?
▷