编码最短长度的字符串
难度:
标签:
题目描述
代码结果
运行时间: 56 ms, 内存: 16.8 MB
/*
* Problem: Encode the shortest length of a string using Java Streams
* Idea: Similar to the standard Java solution but using Java Streams for operations where applicable.
*/
import java.util.stream.IntStream;
public class EncodeShortestLengthStream {
public String encode(String s) {
int n = s.length();
String[][] dp = new String[n][n];
IntStream.range(1, n + 1).forEach(len -> {
IntStream.range(0, n - len + 1).forEach(i -> {
int j = i + len - 1;
String substr = s.substring(i, j + 1);
dp[i][j] = substr;
IntStream.range(i, j).forEach(k -> {
if ((dp[i][k] + dp[k + 1][j]).length() < dp[i][j].length()) {
dp[i][j] = dp[i][k] + dp[k + 1][j];
}
});
String pattern = findPattern(substr);
if (pattern.length() < substr.length()) {
dp[i][j] = pattern;
}
});
});
return dp[0][n - 1];
}
private String findPattern(String s) {
int n = s.length();
return IntStream.rangeClosed(1, n / 2)
.filter(k -> n % k == 0 && s.replace(s.substring(0, k), "").isEmpty())
.mapToObj(k -> n / k + "[" + dpEncode(s.substring(0, k)) + "]")
.findFirst()
.orElse(s);
}
private String dpEncode(String s) {
return encode(s);
}
}
解释
方法:
这个题解采用递归的方式进行字符串压缩。主要思路是将字符串切分成两半,左边一半如果能够按照整倍数压缩,就进行压缩,得到左边一半的最短压缩形式。然后递归处理右边一半,将两半处理完后的字符串拼接起来,其中最短的拼接字符串就是最终的答案。在判断能否进行整倍数压缩时,问题转化为寻找字符串的重复子串。
时间复杂度:
O(n^2)
空间复杂度:
O(n)
代码细节讲解
🦆
题解中提到的字符串压缩算法是否能确保找到全局最短的压缩结果,还是可能只是局部最优解?
▷🦆
递归方法中,为什么选择将字符串平分为两半进行处理?是否有考虑过其他分割方式可能更优?
▷🦆
在寻找重复子串时,你是如何确保找到的是最小的可重复单元,从而实现最大程度的压缩?
▷🦆
在处理字符串切分和拼接时,有没有可能遇到字符串过长导致性能问题,如果有,如何解决?
▷相关问题
字符串解码
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string]
,表示其中方括号内部的 encoded_string
正好重复 k
次。注意 k
保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k
,例如不会出现像 3a
或 2[4]
的输入。
示例 1:
输入:s = "3[a]2[bc]" 输出:"aaabcbc"
示例 2:
输入:s = "3[a2[c]]" 输出:"accaccacc"
示例 3:
输入:s = "2[abc]3[cd]ef" 输出:"abcabccdcdcdef"
示例 4:
输入:s = "abc3[cd]xyz" 输出:"abccdcdcdxyz"
提示:
1 <= s.length <= 30
s
由小写英文字母、数字和方括号'[]'
组成s
保证是一个 有效 的输入。s
中所有整数的取值范围为[1, 300]
原子的数量
给你一个字符串化学式 formula
,返回 每种原子的数量 。
原子总是以一个大写字母开始,接着跟随 0 个或任意个小写字母,表示原子的名字。
如果数量大于 1,原子后会跟着数字表示原子的数量。如果数量等于 1 则不会跟数字。
- 例如,
"H2O"
和"H2O2"
是可行的,但"H1O2"
这个表达是不可行的。
两个化学式连在一起可以构成新的化学式。
- 例如
"H2O2He3Mg4"
也是化学式。
由括号括起的化学式并佐以数字(可选择性添加)也是化学式。
- 例如
"(H2O2)"
和"(H2O2)3"
是化学式。
返回所有原子的数量,格式为:第一个(按字典序)原子的名字,跟着它的数量(如果数量大于 1),然后是第二个原子的名字(按字典序),跟着它的数量(如果数量大于 1),以此类推。
示例 1:
输入:formula = "H2O" 输出:"H2O" 解释:原子的数量是 {'H': 2, 'O': 1}。
示例 2:
输入:formula = "Mg(OH)2" 输出:"H2MgO2" 解释:原子的数量是 {'H': 2, 'Mg': 1, 'O': 2}。
示例 3:
输入:formula = "K4(ON(SO3)2)2" 输出:"K4N2O14S4" 解释:原子的数量是 {'K': 4, 'N': 2, 'O': 14, 'S': 4}。
提示:
1 <= formula.length <= 1000
formula
由英文字母、数字、'('
和')'
组成formula
总是有效的化学式