给你三个整数 x ,y 和 z 。
这三个整数表示你有 x 个 “AA” 字符串,y 个 “BB” 字符串,和 z 个 “AB” 字符串。你需要选择这些字符串中的部分字符串(可以全部选择也可以一个都不选择),将它们按顺序连接得到一个新的字符串。新字符串不能包含子字符串 “AAA” 或者 “BBB” 。
请你返回 新字符串的最大可能长度。
子字符串 是一个字符串中一段连续 非空 的字符序列。
深度优先搜索
先选择一个开头,后面继续选择,判断能获得的最大长度。
比如,先选择 “AA”,那么后一个只能选择 “AB” 或 “BB”。迭代计算。
完整代码
class Solution {
public int longestString(int x, int y, int z) {
int res = 0;
if (x > 0) {
res = Math.max(res, maxLength(0, x - 1, y, z) + 1);
}
if (y > 0) {
res = Math.max(res, maxLength(1, x, y - 1, z) + 1);
}
if (z > 0) {
res = Math.max(res, maxLength(1, x, y, z - 1) + 1);
}
return res * 2;
}
// before 0 表示上一个字符为 A,1 表示为 B
public int maxLength(int before, int x, int y, int z) {
int count = 0;
if (before == 0) {
if (y > 0) {
count = Math.max(count, maxLength(1, x, y - 1, z) + 1);
}
} else {
if (x > 0) {
count = Math.max(count, maxLength(0, x - 1, y, z) + 1);
}
if (z > 0) {
count = Math.max(count, maxLength(1, x, y, z - 1) + 1);
}
}
return count;
}
}
此方法对于大的数据会超出时间限制。
动态规划
与深度优先搜索类似,深度因为有很多参数相同的重复计算,因此会浪费时间。
创建一个四维数组用来保存计算结果,避免重复计算。
完整代码
class Solution {
int[][][][] dp;
public int longestString(int x, int y, int z) {
dp = new int[2][x + 1][y + 1][z + 1];
int res = 0;
if (x > 0) {
res = Math.max(res, maxLength(0, x - 1, y, z) + 1);
}
if (y > 0) {
res = Math.max(res, maxLength(1, x, y - 1, z) + 1);
}
if (z > 0) {
res = Math.max(res, maxLength(1, x, y, z - 1) + 1);
}
return res * 2;
}
// before 0 表示上一个字符为 A,1 表示为 B
public int maxLength(int before, int x, int y, int z) {
if (dp[before][x][y][z] != 0) return dp[before][x][y][z];
int count = 0;
if (before == 0) {
if (y > 0) {
count = Math.max(count, maxLength(1, x, y - 1, z) + 1);
}
} else {
if (x > 0) {
count = Math.max(count, maxLength(0, x - 1, y, z) + 1);
}
if (z > 0) {
count = Math.max(count, maxLength(1, x, y, z - 1) + 1);
}
}
dp[before][x][y][z] = count;
return count;
}
}
增加 1 个 int[2][x + 1][y + 1][z + 1] 的四维数组来保存计算结果,如果已经计算过就直接取值,如果没计算过就计算,并在最后把结果保存进去。
。。。。
不知道取个什么名字好,哈哈哈
解法来自题解。
首先我们只考虑 “AA” 和 “BB” 那么组成的最长长度就是 Math.min(x, y) * 2 + (x != y ? 1 : 0)
。“AA" 和 “BB” 拼接,用两个的最小值乘以 2;如果一个比一个多,就可以放在拼接后的某一端,因此加一。
然后将 “AB” 插入其中,会发现,它无能多少个都可以插入进去的,因此直接加 z。
可能会考虑,如果插入 “AB” 后,那么 “AA” 或 “BB” 多的一方。能否多插入。
多的是 “AA”,
在其前面放入一个 “AB”, 再在其前面是无法再放一个 “AA” 的,就算在其前面放入多个 “AB”,也是不能放的。
在其后面放入一个 “AB”,明显不满足。
多的是 “BB”
不能在其前面放入 “AB”.
在其后面放入 “AB”,同样的道理,也是不能再放入一个 “BB” 的。
因此,插入 “AB”,并不能改变前者的数量。
完整代码
class Solution {
public int longestString(int x, int y, int z) {
return (Math.min(x, y) * 2 + (x != y ? 1 : 0) + z) * 2;
}
}